First working compilation.
This commit is contained in:
2
src/dlls/.gitignore
vendored
2
src/dlls/.gitignore
vendored
@@ -1,3 +1,5 @@
|
|||||||
msgs/
|
msgs/
|
||||||
opt.*/
|
opt.*/
|
||||||
debug.*/
|
debug.*/
|
||||||
|
*.o
|
||||||
|
*.so
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
CPP = gcc
|
# COMPILE ONLY WITH GCC 4.8!
|
||||||
BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp
|
|
||||||
CPPFLAGS = ${BASEFLAGS} -m386 -O2 -w -I. -I../engine -I../common -I../pm_shared -I../../metamod
|
CPP = g++
|
||||||
|
BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp -m32
|
||||||
|
OPTFLAGS = -O2
|
||||||
|
CPPFLAGS = ${BASEFLAGS} ${OPTFLAGS} -w -I. -I../engine -I../common -I../pm_shared -I../metamod
|
||||||
|
|
||||||
OBJ = \
|
OBJ = \
|
||||||
agrunt.o \
|
agrunt.o \
|
||||||
@@ -42,7 +45,7 @@ OBJ = \
|
|||||||
zombie.o
|
zombie.o
|
||||||
|
|
||||||
monster_mm_i386.so: ${OBJ}
|
monster_mm_i386.so: ${OBJ}
|
||||||
${CPP} -fPIC -shared -o $@ ${OBJ}
|
${CPP} -m32 -fPIC -shared -o $@ ${OBJ}
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-rm -f *.o
|
-rm -f *.o
|
||||||
|
|||||||
@@ -315,6 +315,7 @@ int GetAnimationEvent( void *pmodel, entvars_t *pev, MonsterEvent_t *pMonsterEve
|
|||||||
float SetController( void *pmodel, entvars_t *pev, int iController, float flValue )
|
float SetController( void *pmodel, entvars_t *pev, int iController, float flValue )
|
||||||
{
|
{
|
||||||
studiohdr_t *pstudiohdr;
|
studiohdr_t *pstudiohdr;
|
||||||
|
int i;
|
||||||
|
|
||||||
pstudiohdr = (studiohdr_t *)pmodel;
|
pstudiohdr = (studiohdr_t *)pmodel;
|
||||||
if (! pstudiohdr)
|
if (! pstudiohdr)
|
||||||
@@ -323,7 +324,7 @@ float SetController( void *pmodel, entvars_t *pev, int iController, float flValu
|
|||||||
mstudiobonecontroller_t *pbonecontroller = (mstudiobonecontroller_t *)((byte *)pstudiohdr + pstudiohdr->bonecontrollerindex);
|
mstudiobonecontroller_t *pbonecontroller = (mstudiobonecontroller_t *)((byte *)pstudiohdr + pstudiohdr->bonecontrollerindex);
|
||||||
|
|
||||||
// find first controller that matches the index
|
// find first controller that matches the index
|
||||||
for (int i = 0; i < pstudiohdr->numbonecontrollers; i++, pbonecontroller++)
|
for (i = 0; i < pstudiohdr->numbonecontrollers; i++, pbonecontroller++)
|
||||||
{
|
{
|
||||||
if (pbonecontroller->index == iController)
|
if (pbonecontroller->index == iController)
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -53,12 +53,12 @@ void CMApache :: Spawn( void )
|
|||||||
|
|
||||||
if (pev->spawnflags & SF_WAITFORTRIGGER)
|
if (pev->spawnflags & SF_WAITFORTRIGGER)
|
||||||
{
|
{
|
||||||
SetUse( StartupUse );
|
SetUse( &CMApache::StartupUse );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetThink( HuntThink );
|
SetThink( &CMApache::HuntThink );
|
||||||
SetTouch( FlyTouch );
|
SetTouch( &CMApache::FlyTouch );
|
||||||
pev->nextthink = gpGlobals->time + 1.0;
|
pev->nextthink = gpGlobals->time + 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,8 +122,8 @@ void CMApache::NullThink( void )
|
|||||||
|
|
||||||
void CMApache::StartupUse( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
|
void CMApache::StartupUse( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
|
||||||
{
|
{
|
||||||
SetThink( HuntThink );
|
SetThink( &CMApache::HuntThink );
|
||||||
SetTouch( FlyTouch );
|
SetTouch( &CMApache::FlyTouch );
|
||||||
pev->nextthink = gpGlobals->time + 0.1;
|
pev->nextthink = gpGlobals->time + 0.1;
|
||||||
SetUse( NULL );
|
SetUse( NULL );
|
||||||
}
|
}
|
||||||
@@ -136,8 +136,8 @@ void CMApache :: Killed( entvars_t *pevAttacker, int iGib )
|
|||||||
STOP_SOUND( ENT(pev), CHAN_STATIC, "apache/ap_rotor2.wav" );
|
STOP_SOUND( ENT(pev), CHAN_STATIC, "apache/ap_rotor2.wav" );
|
||||||
|
|
||||||
UTIL_SetSize( pev, Vector( -32, -32, -64), Vector( 32, 32, 0) );
|
UTIL_SetSize( pev, Vector( -32, -32, -64), Vector( 32, 32, 0) );
|
||||||
SetThink( DyingThink );
|
SetThink( &CMApache::DyingThink );
|
||||||
SetTouch( CrashTouch );
|
SetTouch( &CMApache::CrashTouch );
|
||||||
pev->nextthink = gpGlobals->time + 0.1;
|
pev->nextthink = gpGlobals->time + 0.1;
|
||||||
pev->health = 0;
|
pev->health = 0;
|
||||||
pev->takedamage = DAMAGE_NO;
|
pev->takedamage = DAMAGE_NO;
|
||||||
@@ -346,7 +346,7 @@ jlb*/
|
|||||||
WRITE_BYTE( BREAK_METAL );
|
WRITE_BYTE( BREAK_METAL );
|
||||||
MESSAGE_END();
|
MESSAGE_END();
|
||||||
|
|
||||||
SetThink( SUB_Remove );
|
SetThink( &CMApache::SUB_Remove );
|
||||||
pev->nextthink = gpGlobals->time + 0.1;
|
pev->nextthink = gpGlobals->time + 0.1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -899,8 +899,8 @@ void CMApacheHVR :: Spawn( void )
|
|||||||
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
|
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
|
||||||
UTIL_SetOrigin( pev, pev->origin );
|
UTIL_SetOrigin( pev, pev->origin );
|
||||||
|
|
||||||
SetThink( IgniteThink );
|
SetThink( &CMApacheHVR::IgniteThink );
|
||||||
SetTouch( ExplodeTouch );
|
SetTouch( &CMApacheHVR::ExplodeTouch );
|
||||||
|
|
||||||
UTIL_MakeAimVectors( pev->angles );
|
UTIL_MakeAimVectors( pev->angles );
|
||||||
m_vecForward = gpGlobals->v_forward;
|
m_vecForward = gpGlobals->v_forward;
|
||||||
@@ -946,7 +946,7 @@ void CMApacheHVR :: IgniteThink( void )
|
|||||||
MESSAGE_END(); // move PHS/PVS data sending into here (SEND_ALL, SEND_PVS, SEND_PHS)
|
MESSAGE_END(); // move PHS/PVS data sending into here (SEND_ALL, SEND_PVS, SEND_PHS)
|
||||||
|
|
||||||
// set to accelerate
|
// set to accelerate
|
||||||
SetThink( AccelerateThink );
|
SetThink( &CMApacheHVR::AccelerateThink );
|
||||||
pev->nextthink = gpGlobals->time + 0.1;
|
pev->nextthink = gpGlobals->time + 0.1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1141,7 +1141,7 @@ CMBMortar *CMBMortar::Shoot( edict_t *pOwner, Vector vecStart, Vector vecVelocit
|
|||||||
pSpit->pev->velocity = vecVelocity;
|
pSpit->pev->velocity = vecVelocity;
|
||||||
pSpit->pev->owner = pOwner;
|
pSpit->pev->owner = pOwner;
|
||||||
pSpit->pev->scale = 2.5;
|
pSpit->pev->scale = 2.5;
|
||||||
pSpit->SetThink ( Animate );
|
pSpit->SetThink ( &CMBMortar::Animate );
|
||||||
pSpit->pev->nextthink = gpGlobals->time + 0.1;
|
pSpit->pev->nextthink = gpGlobals->time + 0.1;
|
||||||
}
|
}
|
||||||
return pSpit;
|
return pSpit;
|
||||||
|
|||||||
@@ -111,9 +111,9 @@ void CSquidSpit::Shoot( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity
|
|||||||
pSpit->pev->velocity = vecVelocity;
|
pSpit->pev->velocity = vecVelocity;
|
||||||
pSpit->pev->owner = ENT(pevOwner);
|
pSpit->pev->owner = ENT(pevOwner);
|
||||||
|
|
||||||
pSpit->SetThink ( Animate );
|
pSpit->SetThink ( &CSquidSpit::Animate );
|
||||||
pSpit->pev->nextthink = gpGlobals->time + 0.1;
|
pSpit->pev->nextthink = gpGlobals->time + 0.1;
|
||||||
pSpit->SetTouch ( SpitTouch );
|
pSpit->SetTouch ( &CSquidSpit::SpitTouch );
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSquidSpit :: SpitTouch ( edict_t *pOther )
|
void CSquidSpit :: SpitTouch ( edict_t *pOther )
|
||||||
@@ -168,7 +168,7 @@ void CSquidSpit :: SpitTouch ( edict_t *pOther )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SetThink ( SUB_Remove );
|
SetThink ( &CSquidSpit::SUB_Remove );
|
||||||
pev->nextthink = gpGlobals->time;
|
pev->nextthink = gpGlobals->time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -483,7 +483,7 @@ public:
|
|||||||
BOOL FValidateHintType ( short sHint );
|
BOOL FValidateHintType ( short sHint );
|
||||||
BOOL FCanActiveIdle ( void );
|
BOOL FCanActiveIdle ( void );
|
||||||
Schedule_t *GetScheduleOfType ( int Type );
|
Schedule_t *GetScheduleOfType ( int Type );
|
||||||
Schedule_t *CMHoundeye :: GetSchedule( void );
|
Schedule_t *GetSchedule( void );
|
||||||
|
|
||||||
CUSTOM_SCHEDULES;
|
CUSTOM_SCHEDULES;
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ void CMGib :: SpawnStickyGibs( entvars_t *pevVictim, Vector vecOrigin, int cGibs
|
|||||||
pGib->pev->movetype = MOVETYPE_TOSS;
|
pGib->pev->movetype = MOVETYPE_TOSS;
|
||||||
pGib->pev->solid = SOLID_BBOX;
|
pGib->pev->solid = SOLID_BBOX;
|
||||||
UTIL_SetSize ( pGib->pev, Vector ( 0, 0 ,0 ), Vector ( 0, 0, 0 ) );
|
UTIL_SetSize ( pGib->pev, Vector ( 0, 0 ,0 ), Vector ( 0, 0, 0 ) );
|
||||||
pGib->SetTouch ( StickyGibTouch );
|
pGib->SetTouch ( &CMGib::StickyGibTouch );
|
||||||
pGib->SetThink (NULL);
|
pGib->SetThink (NULL);
|
||||||
}
|
}
|
||||||
pGib->LimitVelocity();
|
pGib->LimitVelocity();
|
||||||
@@ -327,7 +327,7 @@ void CMBaseMonster :: GibMonster( void )
|
|||||||
if ( gibbed )
|
if ( gibbed )
|
||||||
{
|
{
|
||||||
// don't remove players!
|
// don't remove players!
|
||||||
SetThink ( SUB_Remove );
|
SetThink ( &CMBaseMonster::SUB_Remove );
|
||||||
pev->nextthink = gpGlobals->time;
|
pev->nextthink = gpGlobals->time;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -655,7 +655,7 @@ void CMBaseEntity :: SUB_StartFadeOut ( void )
|
|||||||
pev->avelocity = g_vecZero;
|
pev->avelocity = g_vecZero;
|
||||||
|
|
||||||
pev->nextthink = gpGlobals->time + 0.1;
|
pev->nextthink = gpGlobals->time + 0.1;
|
||||||
SetThink ( SUB_FadeOut );
|
SetThink ( &CMBaseEntity::SUB_FadeOut );
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMBaseEntity :: SUB_FadeOut ( void )
|
void CMBaseEntity :: SUB_FadeOut ( void )
|
||||||
@@ -669,7 +669,7 @@ void CMBaseEntity :: SUB_FadeOut ( void )
|
|||||||
{
|
{
|
||||||
pev->renderamt = 0;
|
pev->renderamt = 0;
|
||||||
pev->nextthink = gpGlobals->time + 0.2;
|
pev->nextthink = gpGlobals->time + 0.2;
|
||||||
SetThink ( SUB_Remove );
|
SetThink ( &CMBaseEntity::SUB_Remove );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -689,7 +689,7 @@ void CMGib :: WaitTillLand ( void )
|
|||||||
|
|
||||||
if ( pev->velocity == g_vecZero )
|
if ( pev->velocity == g_vecZero )
|
||||||
{
|
{
|
||||||
SetThink (SUB_StartFadeOut);
|
SetThink ( &CMGib::SUB_StartFadeOut );
|
||||||
pev->nextthink = gpGlobals->time + m_lifeTime;
|
pev->nextthink = gpGlobals->time + m_lifeTime;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -740,7 +740,7 @@ void CMGib :: StickyGibTouch ( edict_t *pOther )
|
|||||||
Vector vecSpot;
|
Vector vecSpot;
|
||||||
TraceResult tr;
|
TraceResult tr;
|
||||||
|
|
||||||
SetThink ( SUB_Remove );
|
SetThink ( &CMGib::SUB_Remove );
|
||||||
pev->nextthink = gpGlobals->time + 5;
|
pev->nextthink = gpGlobals->time + 5;
|
||||||
|
|
||||||
if (!FStrEq(STRING(pOther->v.classname), "worldspawn"))
|
if (!FStrEq(STRING(pOther->v.classname), "worldspawn"))
|
||||||
@@ -781,8 +781,8 @@ void CMGib :: Spawn( const char *szGibModel )
|
|||||||
|
|
||||||
pev->nextthink = gpGlobals->time + 4;
|
pev->nextthink = gpGlobals->time + 4;
|
||||||
m_lifeTime = 10;
|
m_lifeTime = 10;
|
||||||
SetThink ( WaitTillLand );
|
SetThink ( &CMGib::WaitTillLand );
|
||||||
SetTouch ( BounceGibTouch );
|
SetTouch ( &CMGib::BounceGibTouch );
|
||||||
|
|
||||||
m_material = matNone;
|
m_material = matNone;
|
||||||
m_cBloodDecals = 5;// how many blood decals this gib can place (1 per bounce until none remain).
|
m_cBloodDecals = 5;// how many blood decals this gib can place (1 per bounce until none remain).
|
||||||
|
|||||||
@@ -1104,8 +1104,8 @@ void CMControllerHeadBall :: Spawn( void )
|
|||||||
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
|
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
|
||||||
UTIL_SetOrigin( pev, pev->origin );
|
UTIL_SetOrigin( pev, pev->origin );
|
||||||
|
|
||||||
SetThink( HuntThink );
|
SetThink( &CMControllerHeadBall::HuntThink );
|
||||||
SetTouch( BounceTouch );
|
SetTouch( &CMControllerHeadBall::BounceTouch );
|
||||||
|
|
||||||
m_vecIdeal = Vector( 0, 0, 0 );
|
m_vecIdeal = Vector( 0, 0, 0 );
|
||||||
|
|
||||||
@@ -1198,7 +1198,7 @@ void CMControllerHeadBall :: HuntThink( void )
|
|||||||
|
|
||||||
m_flNextAttack = gpGlobals->time + 3.0;
|
m_flNextAttack = gpGlobals->time + 3.0;
|
||||||
|
|
||||||
SetThink( DieThink );
|
SetThink( &CMControllerHeadBall::DieThink );
|
||||||
pev->nextthink = gpGlobals->time + 0.3;
|
pev->nextthink = gpGlobals->time + 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1291,8 +1291,8 @@ void CMControllerZapBall :: Spawn( void )
|
|||||||
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
|
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
|
||||||
UTIL_SetOrigin( pev, pev->origin );
|
UTIL_SetOrigin( pev, pev->origin );
|
||||||
|
|
||||||
SetThink( AnimateThink );
|
SetThink( &CMControllerZapBall::AnimateThink );
|
||||||
SetTouch( ExplodeTouch );
|
SetTouch( &CMControllerZapBall::ExplodeTouch );
|
||||||
|
|
||||||
m_hOwner = pev->owner;
|
m_hOwner = pev->owner;
|
||||||
pev->dmgtime = gpGlobals->time; // keep track of when ball spawned
|
pev->dmgtime = gpGlobals->time; // keep track of when ball spawned
|
||||||
|
|||||||
@@ -115,7 +115,8 @@ monster_type_t monster_types[]=
|
|||||||
"scientist", FALSE,
|
"scientist", FALSE,
|
||||||
"snark", FALSE,
|
"snark", FALSE,
|
||||||
"zombie", FALSE,
|
"zombie", FALSE,
|
||||||
"", FALSE};
|
"", FALSE
|
||||||
|
};
|
||||||
|
|
||||||
monster_t monsters[MAX_MONSTER_ENTS];
|
monster_t monsters[MAX_MONSTER_ENTS];
|
||||||
int monster_ents_used = 0;
|
int monster_ents_used = 0;
|
||||||
@@ -326,7 +327,7 @@ bool spawn_monster(int monster_type, Vector origin, float angle, int respawn_ind
|
|||||||
|
|
||||||
if ((monster_index = GetMonsterIndex()) == -1)
|
if ((monster_index = GetMonsterIndex()) == -1)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: No FREE Monster edicts!");
|
//META_CONS("[MONSTER] ERROR: No FREE Monster edicts!");
|
||||||
LOG_MESSAGE(PLID, "ERROR: No FREE Monster edicts!");
|
LOG_MESSAGE(PLID, "ERROR: No FREE Monster edicts!");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -336,10 +337,11 @@ bool spawn_monster(int monster_type, Vector origin, float angle, int respawn_ind
|
|||||||
{
|
{
|
||||||
char msg[256];
|
char msg[256];
|
||||||
|
|
||||||
META_CONS("[MONSTER] ERROR: You can't spawn monster %s since it wasn't precached!",
|
//META_CONS("[MONSTER] ERROR: You can't spawn monster %s since it wasn't precached!", monster_types[monster_type].name);
|
||||||
monster_types[monster_type].name);
|
LOG_MESSAGE(PLID, "ERROR: You can't spawn monster %s since it wasn't precached!", monster_types[monster_type].name);
|
||||||
|
|
||||||
META_CONS("[MONSTER] valid precached monster names are:");
|
//META_CONS("[MONSTER] valid precached monster names are:");
|
||||||
|
LOG_MESSAGE(PLID, "valid precached monster names are:");
|
||||||
msg[0] = 0;
|
msg[0] = 0;
|
||||||
for (int index = 0; monster_types[index].name[0]; index++)
|
for (int index = 0; monster_types[index].name[0]; index++)
|
||||||
{
|
{
|
||||||
@@ -349,52 +351,42 @@ bool spawn_monster(int monster_type, Vector origin, float angle, int respawn_ind
|
|||||||
strcat(msg, " ");
|
strcat(msg, " ");
|
||||||
if (strlen(msg) > 60)
|
if (strlen(msg) > 60)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] %s", msg);
|
//META_CONS("[MONSTER] %s", msg);
|
||||||
|
LOG_MESSAGE(PLID, "%s", msg);
|
||||||
msg[0] = 0;
|
msg[0] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (msg[0])
|
if (msg[0])
|
||||||
META_CONS("[MONSTER] %s", msg);
|
{
|
||||||
|
//META_CONS("[MONSTER] %s", msg);
|
||||||
|
LOG_MESSAGE(PLID, "%s", msg);
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (monster_type)
|
switch (monster_type)
|
||||||
{
|
{
|
||||||
case 0: monsters[monster_index].pMonster = CreateClassPtr((CMAGrunt *)NULL);
|
case 0: monsters[monster_index].pMonster = CreateClassPtr((CMAGrunt *)NULL); break;
|
||||||
break;
|
case 1: monsters[monster_index].pMonster = CreateClassPtr((CMApache *)NULL); break;
|
||||||
case 1: monsters[monster_index].pMonster = CreateClassPtr((CMApache *)NULL);
|
case 2: monsters[monster_index].pMonster = CreateClassPtr((CMBarney *)NULL); break;
|
||||||
break;
|
case 3: monsters[monster_index].pMonster = CreateClassPtr((CMBigMomma *)NULL); break;
|
||||||
case 2: monsters[monster_index].pMonster = CreateClassPtr((CMBarney *)NULL);
|
case 4: monsters[monster_index].pMonster = CreateClassPtr((CMBullsquid *)NULL); break;
|
||||||
break;
|
case 5: monsters[monster_index].pMonster = CreateClassPtr((CMController *)NULL); break;
|
||||||
case 3: monsters[monster_index].pMonster = CreateClassPtr((CMBigMomma *)NULL);
|
case 6: monsters[monster_index].pMonster = CreateClassPtr((CMHAssassin *)NULL); break;
|
||||||
break;
|
case 7: monsters[monster_index].pMonster = CreateClassPtr((CMHeadCrab *)NULL); break;
|
||||||
case 4: monsters[monster_index].pMonster = CreateClassPtr((CMBullsquid *)NULL);
|
case 8: monsters[monster_index].pMonster = CreateClassPtr((CMHGrunt *)NULL); break;
|
||||||
break;
|
case 9: monsters[monster_index].pMonster = CreateClassPtr((CMHoundeye *)NULL); break;
|
||||||
case 5: monsters[monster_index].pMonster = CreateClassPtr((CMController *)NULL);
|
case 10: monsters[monster_index].pMonster = CreateClassPtr((CMISlave *)NULL); break;
|
||||||
break;
|
case 11: monsters[monster_index].pMonster = CreateClassPtr((CMScientist *)NULL); break;
|
||||||
case 6: monsters[monster_index].pMonster = CreateClassPtr((CMHAssassin *)NULL);
|
case 12: monsters[monster_index].pMonster = CreateClassPtr((CMSqueakGrenade *)NULL); break;
|
||||||
break;
|
case 13: monsters[monster_index].pMonster = CreateClassPtr((CMZombie *)NULL); break;
|
||||||
case 7: monsters[monster_index].pMonster = CreateClassPtr((CMHeadCrab *)NULL);
|
|
||||||
break;
|
|
||||||
case 8: monsters[monster_index].pMonster = CreateClassPtr((CMHGrunt *)NULL);
|
|
||||||
break;
|
|
||||||
case 9: monsters[monster_index].pMonster = CreateClassPtr((CMHoundeye *)NULL);
|
|
||||||
break;
|
|
||||||
case 10: monsters[monster_index].pMonster = CreateClassPtr((CMISlave *)NULL);
|
|
||||||
break;
|
|
||||||
case 11: monsters[monster_index].pMonster = CreateClassPtr((CMScientist *)NULL);
|
|
||||||
break;
|
|
||||||
case 12: monsters[monster_index].pMonster = CreateClassPtr((CMSqueakGrenade *)NULL);
|
|
||||||
break;
|
|
||||||
case 13: monsters[monster_index].pMonster = CreateClassPtr((CMZombie *)NULL);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (monsters[monster_index].pMonster == NULL)
|
if (monsters[monster_index].pMonster == NULL)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: Error Creating Monster!" );
|
//META_CONS("[MONSTER] ERROR: Error Creating Monster!" );
|
||||||
LOG_MESSAGE(PLID, "ERROR: Error Creating Monster!");
|
LOG_MESSAGE(PLID, "ERROR: Error Creating Monster!");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -521,8 +513,8 @@ void MonsterCommand(void)
|
|||||||
|
|
||||||
if ((player_index < 1) || (player_index > gpGlobals->maxClients))
|
if ((player_index < 1) || (player_index > gpGlobals->maxClients))
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] invalid player index! (%d to %d allowed)",
|
//META_CONS("[MONSTER] invalid player index! (%d to %d allowed)", 1, gpGlobals->maxClients);
|
||||||
1, gpGlobals->maxClients);
|
LOG_MESSAGE(PLID, "invalid player index! (%d to %d allowed)", 1, gpGlobals->maxClients);
|
||||||
player_index = -1;
|
player_index = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -544,7 +536,8 @@ void MonsterCommand(void)
|
|||||||
|
|
||||||
if (player_index == -1)
|
if (player_index == -1)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] can't find player named \"%s\"!", parg2);
|
//META_CONS("[MONSTER] can't find player named \"%s\"!", parg2);
|
||||||
|
LOG_MESSAGE(PLID, "can't find player named \"%s\"!", parg2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -555,8 +548,8 @@ void MonsterCommand(void)
|
|||||||
|
|
||||||
if ((pPlayer == NULL) || (pPlayer->free))
|
if ((pPlayer == NULL) || (pPlayer->free))
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] player index %d is not a valid player!",
|
//META_CONS("[MONSTER] player index %d is not a valid player!", player_index);
|
||||||
player_index);
|
LOG_MESSAGE(PLID, "player index %d is not a valid player!", player_index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -564,15 +557,15 @@ void MonsterCommand(void)
|
|||||||
|
|
||||||
if (player_name[0] == 0)
|
if (player_name[0] == 0)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] player index %d is not a valid player!",
|
//META_CONS("[MONSTER] player index %d is not a valid player!", player_index);
|
||||||
player_index);
|
LOG_MESSAGE(PLID, "player index %d is not a valid player!", player_index);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!UTIL_IsAlive(pPlayer))
|
if (!UTIL_IsAlive(pPlayer))
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] player \"%s\" is not alive or is an observer!",
|
//META_CONS("[MONSTER] player \"%s\" is not alive or is an observer!", player_name);
|
||||||
player_name);
|
LOG_MESSAGE(PLID, "player \"%s\" is not alive or is an observer!", player_name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -752,16 +745,18 @@ void MonsterCommand(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
META_CONS("[MONSTER] there's no room to spawn a monster near player \"%s\"!",
|
//META_CONS("[MONSTER] there's no room to spawn a monster near player \"%s\"!", player_name);
|
||||||
player_name);
|
LOG_MESSAGE(PLID, "there's no room to spawn a monster near player \"%s\"!", player_name);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
META_CONS("[MONSTER] usage: monster monster_name player_name | #player_index");
|
//META_CONS("[MONSTER] usage: monster monster_name player_name | #player_index");
|
||||||
META_CONS("[MONSTER] valid monster_names are:");
|
//META_CONS("[MONSTER] valid monster_names are:");
|
||||||
|
LOG_MESSAGE(PLID, "usage: monster monster_name player_name | #player_index");
|
||||||
|
LOG_MESSAGE(PLID, "valid monster_names are:");
|
||||||
msg[0] = 0;
|
msg[0] = 0;
|
||||||
for (index = 0; monster_types[index].name[0]; index++)
|
for (index = 0; monster_types[index].name[0]; index++)
|
||||||
{
|
{
|
||||||
@@ -769,12 +764,16 @@ void MonsterCommand(void)
|
|||||||
strcat(msg, " ");
|
strcat(msg, " ");
|
||||||
if (strlen(msg) > 60)
|
if (strlen(msg) > 60)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] %s", msg);
|
//META_CONS("[MONSTER] %s", msg);
|
||||||
|
LOG_MESSAGE(PLID, "%s", msg);
|
||||||
msg[0] = 0;
|
msg[0] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (msg[0])
|
if (msg[0])
|
||||||
META_CONS("[MONSTER] %s", msg);
|
{
|
||||||
|
//META_CONS("[MONSTER] %s", msg);
|
||||||
|
LOG_MESSAGE(PLID, "%s", msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -856,8 +855,7 @@ void mmDispatchTouch( edict_t *pentTouched, edict_t *pentOther )
|
|||||||
{
|
{
|
||||||
for (int index=0; index < monster_ents_used; index++)
|
for (int index=0; index < monster_ents_used; index++)
|
||||||
{
|
{
|
||||||
if ((pentTouched != NULL) &&
|
if ((pentTouched != NULL) && (pentTouched == monsters[index].monster_pent))
|
||||||
(pentTouched == monsters[index].monster_pent))
|
|
||||||
{
|
{
|
||||||
monsters[index].pMonster->Touch(pentOther);
|
monsters[index].pMonster->Touch(pentOther);
|
||||||
|
|
||||||
@@ -905,48 +903,20 @@ void mmServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
|
|||||||
|
|
||||||
switch (index)
|
switch (index)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0: agrunt.Precache(); break;
|
||||||
agrunt.Precache();
|
case 1: apache.Precache(); break;
|
||||||
break;
|
case 2: barney.Precache(); break;
|
||||||
case 1:
|
case 3: bigmomma.Precache(); break;
|
||||||
apache.Precache();
|
case 4: bullsquid.Precache(); break;
|
||||||
break;
|
case 5: controller.Precache(); break;
|
||||||
case 2:
|
case 6: hassassin.Precache(); break;
|
||||||
barney.Precache();
|
case 7: headcrab.Precache(); break;
|
||||||
break;
|
case 8: hgrunt.Precache(); break;
|
||||||
case 3:
|
case 9: houndeye.Precache(); break;
|
||||||
bigmomma.Precache();
|
case 10: islave.Precache(); break;
|
||||||
break;
|
case 11: scientist.Precache(); break;
|
||||||
case 4:
|
case 12: snark.Precache(); break;
|
||||||
bullsquid.Precache();
|
case 13: zombie.Precache(); break;
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
controller.Precache();
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
hassassin.Precache();
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
headcrab.Precache();
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
hgrunt.Precache();
|
|
||||||
break;
|
|
||||||
case 9:
|
|
||||||
houndeye.Precache();
|
|
||||||
break;
|
|
||||||
case 10:
|
|
||||||
islave.Precache();
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
scientist.Precache();
|
|
||||||
break;
|
|
||||||
case 12:
|
|
||||||
snark.Precache();
|
|
||||||
break;
|
|
||||||
case 13:
|
|
||||||
zombie.Precache();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ void CMSprite::Expand( float scaleSpeed, float fadeSpeed )
|
|||||||
{
|
{
|
||||||
pev->speed = scaleSpeed;
|
pev->speed = scaleSpeed;
|
||||||
pev->health = fadeSpeed;
|
pev->health = fadeSpeed;
|
||||||
SetThink( ExpandThink );
|
SetThink( &CMSprite::ExpandThink );
|
||||||
|
|
||||||
pev->nextthink = gpGlobals->time;
|
pev->nextthink = gpGlobals->time;
|
||||||
m_lastTime = gpGlobals->time;
|
m_lastTime = gpGlobals->time;
|
||||||
@@ -421,7 +421,7 @@ void CMSprite::TurnOn( void )
|
|||||||
pev->effects = 0;
|
pev->effects = 0;
|
||||||
if ( (pev->framerate && m_maxFrame > 1.0) || (pev->spawnflags & SF_SPRITE_ONCE) )
|
if ( (pev->framerate && m_maxFrame > 1.0) || (pev->spawnflags & SF_SPRITE_ONCE) )
|
||||||
{
|
{
|
||||||
SetThink( AnimateThink );
|
SetThink( &CMSprite::AnimateThink );
|
||||||
pev->nextthink = gpGlobals->time;
|
pev->nextthink = gpGlobals->time;
|
||||||
m_lastTime = gpGlobals->time;
|
m_lastTime = gpGlobals->time;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ public:
|
|||||||
|
|
||||||
inline void AnimateAndDie( float framerate )
|
inline void AnimateAndDie( float framerate )
|
||||||
{
|
{
|
||||||
SetThink(AnimateUntilDead);
|
SetThink(&CMSprite::AnimateUntilDead);
|
||||||
pev->framerate = framerate;
|
pev->framerate = framerate;
|
||||||
pev->dmgtime = gpGlobals->time + (m_maxFrame / framerate);
|
pev->dmgtime = gpGlobals->time + (m_maxFrame / framerate);
|
||||||
pev->nextthink = gpGlobals->time;
|
pev->nextthink = gpGlobals->time;
|
||||||
@@ -165,7 +165,7 @@ public:
|
|||||||
|
|
||||||
static CMBeam *BeamCreate( const char *pSpriteName, int width );
|
static CMBeam *BeamCreate( const char *pSpriteName, int width );
|
||||||
|
|
||||||
inline void LiveForTime( float time ) { SetThink(SUB_Remove); pev->nextthink = gpGlobals->time + time; }
|
inline void LiveForTime( float time ) { SetThink(&CMBeam::SUB_Remove); pev->nextthink = gpGlobals->time + time; }
|
||||||
inline void BeamDamageInstant( TraceResult *ptr, float damage )
|
inline void BeamDamageInstant( TraceResult *ptr, float damage )
|
||||||
{
|
{
|
||||||
pev->dmg = damage;
|
pev->dmg = damage;
|
||||||
|
|||||||
@@ -49,13 +49,7 @@ typedef int BOOL;
|
|||||||
#define MAX_PATH PATH_MAX
|
#define MAX_PATH PATH_MAX
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#ifndef min
|
|
||||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
|
||||||
#endif
|
|
||||||
#ifndef max
|
|
||||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
|
||||||
#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)
|
#define _vsnprintf(a,b,c,d) vsnprintf(a,b,c,d)
|
||||||
#endif
|
|
||||||
#endif //_WIN32
|
#endif //_WIN32
|
||||||
|
|
||||||
// Misc C-runtime library headers
|
// Misc C-runtime library headers
|
||||||
@@ -63,6 +57,11 @@ typedef int BOOL;
|
|||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
|
|
||||||
|
// min/max is not on math.h library
|
||||||
|
// move outside win32 scope so it can compile on both platforms
|
||||||
|
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
// Header file containing definition of globalvars_t and entvars_t
|
// Header file containing definition of globalvars_t and entvars_t
|
||||||
typedef int func_t; //
|
typedef int func_t; //
|
||||||
typedef int string_t; // from engine's pr_comp.h;
|
typedef int string_t; // from engine's pr_comp.h;
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ void CMGrenade::Explode( TraceResult *pTrace, int bitsDamageType )
|
|||||||
}
|
}
|
||||||
|
|
||||||
pev->effects |= EF_NODRAW;
|
pev->effects |= EF_NODRAW;
|
||||||
SetThink( Smoke );
|
SetThink( &CMGrenade::Smoke );
|
||||||
pev->velocity = g_vecZero;
|
pev->velocity = g_vecZero;
|
||||||
pev->nextthink = gpGlobals->time + 0.3;
|
pev->nextthink = gpGlobals->time + 0.3;
|
||||||
|
|
||||||
@@ -155,13 +155,13 @@ void CMGrenade::Killed( entvars_t *pevAttacker, int iGib )
|
|||||||
// Timed grenade, this think is called when time runs out.
|
// Timed grenade, this think is called when time runs out.
|
||||||
void CMGrenade::DetonateUse( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
|
void CMGrenade::DetonateUse( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
|
||||||
{
|
{
|
||||||
SetThink( Detonate );
|
SetThink( &CMGrenade::Detonate );
|
||||||
pev->nextthink = gpGlobals->time;
|
pev->nextthink = gpGlobals->time;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMGrenade::PreDetonate( void )
|
void CMGrenade::PreDetonate( void )
|
||||||
{
|
{
|
||||||
SetThink( Detonate );
|
SetThink( &CMGrenade::Detonate );
|
||||||
pev->nextthink = gpGlobals->time + 1;
|
pev->nextthink = gpGlobals->time + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,7 +329,7 @@ void CMGrenade :: TumbleThink( void )
|
|||||||
|
|
||||||
if (pev->dmgtime <= gpGlobals->time)
|
if (pev->dmgtime <= gpGlobals->time)
|
||||||
{
|
{
|
||||||
SetThink( Detonate );
|
SetThink( &CMGrenade::Detonate );
|
||||||
}
|
}
|
||||||
if (pev->waterlevel != 0)
|
if (pev->waterlevel != 0)
|
||||||
{
|
{
|
||||||
@@ -370,14 +370,14 @@ CMGrenade *CMGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector
|
|||||||
pGrenade->pev->owner = ENT(pevOwner);
|
pGrenade->pev->owner = ENT(pevOwner);
|
||||||
|
|
||||||
// make monsters afaid of it while in the air
|
// make monsters afaid of it while in the air
|
||||||
pGrenade->SetThink( DangerSoundThink );
|
pGrenade->SetThink( &CMGrenade::DangerSoundThink );
|
||||||
pGrenade->pev->nextthink = gpGlobals->time;
|
pGrenade->pev->nextthink = gpGlobals->time;
|
||||||
|
|
||||||
// Tumble in air
|
// Tumble in air
|
||||||
pGrenade->pev->avelocity.x = RANDOM_FLOAT ( -100, -500 );
|
pGrenade->pev->avelocity.x = RANDOM_FLOAT ( -100, -500 );
|
||||||
|
|
||||||
// Explode on contact
|
// Explode on contact
|
||||||
pGrenade->SetTouch( ExplodeTouch );
|
pGrenade->SetTouch( &CMGrenade::ExplodeTouch );
|
||||||
|
|
||||||
pGrenade->pev->dmg = gSkillData.monDmgM203Grenade;
|
pGrenade->pev->dmg = gSkillData.monDmgM203Grenade;
|
||||||
|
|
||||||
@@ -398,14 +398,14 @@ CMGrenade * CMGrenade:: ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector
|
|||||||
pGrenade->pev->angles = UTIL_VecToAngles(pGrenade->pev->velocity);
|
pGrenade->pev->angles = UTIL_VecToAngles(pGrenade->pev->velocity);
|
||||||
pGrenade->pev->owner = ENT(pevOwner);
|
pGrenade->pev->owner = ENT(pevOwner);
|
||||||
|
|
||||||
pGrenade->SetTouch( BounceTouch ); // Bounce if touched
|
pGrenade->SetTouch( &CMGrenade::BounceTouch ); // Bounce if touched
|
||||||
|
|
||||||
// Take one second off of the desired detonation time and set the think to PreDetonate. PreDetonate
|
// Take one second off of the desired detonation time and set the think to PreDetonate. PreDetonate
|
||||||
// will insert a DANGER sound into the world sound list and delay detonation for one second so that
|
// will insert a DANGER sound into the world sound list and delay detonation for one second so that
|
||||||
// the grenade explodes after the exact amount of time specified in the call to ShootTimed().
|
// the grenade explodes after the exact amount of time specified in the call to ShootTimed().
|
||||||
|
|
||||||
pGrenade->pev->dmgtime = gpGlobals->time + time;
|
pGrenade->pev->dmgtime = gpGlobals->time + time;
|
||||||
pGrenade->SetThink( TumbleThink );
|
pGrenade->SetThink( &CMGrenade::TumbleThink );
|
||||||
pGrenade->pev->nextthink = gpGlobals->time + 0.1;
|
pGrenade->pev->nextthink = gpGlobals->time + 0.1;
|
||||||
if (time < 0.1)
|
if (time < 0.1)
|
||||||
{
|
{
|
||||||
@@ -452,9 +452,9 @@ CMGrenade * CMGrenade :: ShootSatchelCharge( entvars_t *pevOwner, Vector vecStar
|
|||||||
pGrenade->pev->owner = ENT(pevOwner);
|
pGrenade->pev->owner = ENT(pevOwner);
|
||||||
|
|
||||||
// Detonate in "time" seconds
|
// Detonate in "time" seconds
|
||||||
pGrenade->SetThink( SUB_DoNothing );
|
pGrenade->SetThink( &CMGrenade::SUB_DoNothing );
|
||||||
pGrenade->SetUse( DetonateUse );
|
pGrenade->SetUse( &CMGrenade::DetonateUse );
|
||||||
pGrenade->SetTouch( SlideTouch );
|
pGrenade->SetTouch( &CMGrenade::SlideTouch );
|
||||||
pGrenade->pev->spawnflags = SF_DETONATE;
|
pGrenade->pev->spawnflags = SF_DETONATE;
|
||||||
|
|
||||||
pGrenade->pev->friction = 0.9;
|
pGrenade->pev->friction = 0.9;
|
||||||
|
|||||||
@@ -349,7 +349,7 @@ void CMHeadCrab :: StartTask ( Task_t *pTask )
|
|||||||
{
|
{
|
||||||
EMIT_SOUND_DYN( edict(), CHAN_WEAPON, pAttackSounds[0], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
EMIT_SOUND_DYN( edict(), CHAN_WEAPON, pAttackSounds[0], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
|
||||||
m_IdealActivity = ACT_RANGE_ATTACK1;
|
m_IdealActivity = ACT_RANGE_ATTACK1;
|
||||||
SetTouch ( LeapTouch );
|
SetTouch ( &CMHeadCrab::LeapTouch );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -71,8 +71,8 @@ void CMHornet :: Spawn( void )
|
|||||||
SET_MODEL(ENT( pev ), "models/hornet.mdl");
|
SET_MODEL(ENT( pev ), "models/hornet.mdl");
|
||||||
UTIL_SetSize( pev, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ) );
|
UTIL_SetSize( pev, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ) );
|
||||||
|
|
||||||
SetTouch( DieTouch );
|
SetTouch( &CMHornet::DieTouch );
|
||||||
SetThink( StartTrack );
|
SetThink( &CMHornet::StartTrack );
|
||||||
|
|
||||||
edict_t *pSoundEnt = pev->owner;
|
edict_t *pSoundEnt = pev->owner;
|
||||||
if ( !pSoundEnt )
|
if ( !pSoundEnt )
|
||||||
@@ -140,8 +140,8 @@ void CMHornet :: StartTrack ( void )
|
|||||||
{
|
{
|
||||||
IgniteTrail();
|
IgniteTrail();
|
||||||
|
|
||||||
SetTouch( TrackTouch );
|
SetTouch( &CMHornet::TrackTouch );
|
||||||
SetThink( TrackTarget );
|
SetThink( &CMHornet::TrackTarget );
|
||||||
|
|
||||||
pev->nextthink = gpGlobals->time + 0.1;
|
pev->nextthink = gpGlobals->time + 0.1;
|
||||||
}
|
}
|
||||||
@@ -153,9 +153,9 @@ void CMHornet :: StartDart ( void )
|
|||||||
{
|
{
|
||||||
IgniteTrail();
|
IgniteTrail();
|
||||||
|
|
||||||
SetTouch( DartTouch );
|
SetTouch( &CMHornet::DartTouch );
|
||||||
|
|
||||||
SetThink( SUB_Remove );
|
SetThink( &CMHornet::SUB_Remove );
|
||||||
pev->nextthink = gpGlobals->time + 4;
|
pev->nextthink = gpGlobals->time + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ void CMHornet :: TrackTarget ( void )
|
|||||||
if (gpGlobals->time > m_flStopAttack)
|
if (gpGlobals->time > m_flStopAttack)
|
||||||
{
|
{
|
||||||
SetTouch( NULL );
|
SetTouch( NULL );
|
||||||
SetThink( SUB_Remove );
|
SetThink( &CMHornet::SUB_Remove );
|
||||||
pev->nextthink = gpGlobals->time + 0.1;
|
pev->nextthink = gpGlobals->time + 0.1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -366,7 +366,7 @@ void CMHornet::DieTouch ( edict_t *pOther )
|
|||||||
pev->modelindex = 0;// so will disappear for the 0.1 secs we wait until NEXTTHINK gets rid
|
pev->modelindex = 0;// so will disappear for the 0.1 secs we wait until NEXTTHINK gets rid
|
||||||
pev->solid = SOLID_NOT;
|
pev->solid = SOLID_NOT;
|
||||||
|
|
||||||
SetThink ( SUB_Remove );
|
SetThink ( &CMHornet::SUB_Remove );
|
||||||
pev->nextthink = gpGlobals->time + 1;// stick around long enough for the sound to finish!
|
pev->nextthink = gpGlobals->time + 1;// stick around long enough for the sound to finish!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -90,13 +90,13 @@ bool scan_monster_cfg(FILE *fp)
|
|||||||
{
|
{
|
||||||
if (origin)
|
if (origin)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: origin found twice: %s", input);
|
//META_CONS("[MONSTER] ERROR: origin found twice: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: origin found twice: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: origin found twice: %s", input);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
if (sscanf(&input[7], "%f %f %f", &x, &y, &z) != 3)
|
if (sscanf(&input[7], "%f %f %f", &x, &y, &z) != 3)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: invalid origin: %s", input);
|
//META_CONS("[MONSTER] ERROR: invalid origin: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: invalid origin: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: invalid origin: %s", input);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
@@ -109,13 +109,13 @@ bool scan_monster_cfg(FILE *fp)
|
|||||||
{
|
{
|
||||||
if (delay)
|
if (delay)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: delay found twice: %s", input);
|
//META_CONS("[MONSTER] ERROR: delay found twice: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: delay found twice: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: delay found twice: %s", input);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
if (sscanf(&input[6], "%f", &x) != 1)
|
if (sscanf(&input[6], "%f", &x) != 1)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: invalid delay: %s", input);
|
//META_CONS("[MONSTER] ERROR: invalid delay: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: invalid delay: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: invalid delay: %s", input);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
@@ -126,19 +126,19 @@ bool scan_monster_cfg(FILE *fp)
|
|||||||
{
|
{
|
||||||
if (angle)
|
if (angle)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: angle found twice: %s", input);
|
//META_CONS("[MONSTER] ERROR: angle found twice: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: angle found twice: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: angle found twice: %s", input);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
if (angle_min || angle_max)
|
if (angle_min || angle_max)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
//META_CONS("[MONSTER] ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
if (sscanf(&input[6], "%f", &x) != 1)
|
if (sscanf(&input[6], "%f", &x) != 1)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: invalid angle: %s", input);
|
//META_CONS("[MONSTER] ERROR: invalid angle: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: invalid angle: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: invalid angle: %s", input);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
@@ -150,19 +150,19 @@ bool scan_monster_cfg(FILE *fp)
|
|||||||
{
|
{
|
||||||
if (angle_min)
|
if (angle_min)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: angle_min found twice: %s", input);
|
//META_CONS("[MONSTER] ERROR: angle_min found twice: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: angle_min found twice: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: angle_min found twice: %s", input);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
if (angle)
|
if (angle)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
//META_CONS("[MONSTER] ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
if (sscanf(&input[10], "%f", &x) != 1)
|
if (sscanf(&input[10], "%f", &x) != 1)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: invalid angle_min: %s", input);
|
//META_CONS("[MONSTER] ERROR: invalid angle_min: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: invalid angle_min: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: invalid angle_min: %s", input);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
@@ -173,19 +173,19 @@ bool scan_monster_cfg(FILE *fp)
|
|||||||
{
|
{
|
||||||
if (angle_max)
|
if (angle_max)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: angle_max found twice: %s", input);
|
//META_CONS("[MONSTER] ERROR: angle_max found twice: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: angle_max found twice: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: angle_max found twice: %s", input);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
if (angle)
|
if (angle)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
//META_CONS("[MONSTER] ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: you can't specify angle AND angle_min or angle_max: %s", input);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
if (sscanf(&input[10], "%f", &x) != 1)
|
if (sscanf(&input[10], "%f", &x) != 1)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: invalid angle_max: %s", input);
|
//META_CONS("[MONSTER] ERROR: invalid angle_max: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: invalid angle_max: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: invalid angle_max: %s", input);
|
||||||
return TRUE; // error
|
return TRUE; // error
|
||||||
}
|
}
|
||||||
@@ -211,7 +211,7 @@ bool scan_monster_cfg(FILE *fp)
|
|||||||
}
|
}
|
||||||
if (monster_types[index].name[0] == 0)
|
if (monster_types[index].name[0] == 0)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: invalid monster name: %s", input);
|
//META_CONS("[MONSTER] ERROR: invalid monster name: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: invalid monster name: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: invalid monster name: %s", input);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -220,7 +220,7 @@ bool scan_monster_cfg(FILE *fp)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: unknown command: %s", input);
|
//META_CONS("[MONSTER] ERROR: unknown command: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: unknown command: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: unknown command: %s", input);
|
||||||
return TRUE; // error occurred
|
return TRUE; // error occurred
|
||||||
}
|
}
|
||||||
@@ -229,25 +229,25 @@ bool scan_monster_cfg(FILE *fp)
|
|||||||
// check for all necessary fields here...
|
// check for all necessary fields here...
|
||||||
if (!origin)
|
if (!origin)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: you didn't specify an origin!");
|
//META_CONS("[MONSTER] ERROR: you didn't specify an origin!");
|
||||||
LOG_MESSAGE(PLID, "ERROR: you didn't specify an origin!");
|
LOG_MESSAGE(PLID, "ERROR: you didn't specify an origin!");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (angle_min && !angle_max)
|
if (angle_min && !angle_max)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: you specified angle_min but didn't specify angle_max!");
|
//META_CONS("[MONSTER] ERROR: you specified angle_min but didn't specify angle_max!");
|
||||||
LOG_MESSAGE(PLID, "ERROR: you specified angle_min but didn't specify angle_max!");
|
LOG_MESSAGE(PLID, "ERROR: you specified angle_min but didn't specify angle_max!");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (angle_max && !angle_min)
|
if (angle_max && !angle_min)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: you specified angle_max but didn't specify angle_min!");
|
//META_CONS("[MONSTER] ERROR: you specified angle_max but didn't specify angle_min!");
|
||||||
LOG_MESSAGE(PLID, "ERROR: you specified angle_max but didn't specify angle_min!");
|
LOG_MESSAGE(PLID, "ERROR: you specified angle_max but didn't specify angle_min!");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (!monster)
|
if (!monster)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: No monster key found!");
|
//META_CONS("[MONSTER] ERROR: No monster key found!");
|
||||||
LOG_MESSAGE(PLID, "ERROR: No monster key found!");
|
LOG_MESSAGE(PLID, "ERROR: No monster key found!");
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -328,13 +328,13 @@ bool process_monster_cfg(void)
|
|||||||
{
|
{
|
||||||
if (dllapi_log->value)
|
if (dllapi_log->value)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] Processing config file=%s", filename);
|
//META_CONS("[MONSTER] Processing config file=%s", filename);
|
||||||
LOG_MESSAGE(PLID, "Processing config file=%s", filename);
|
LOG_MESSAGE(PLID, "Processing config file=%s", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fp = fopen(filename, "r")) == NULL)
|
if ((fp = fopen(filename, "r")) == NULL)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename);
|
//META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename);
|
||||||
LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\" file!", filename);
|
LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\" file!", filename);
|
||||||
|
|
||||||
return TRUE; // return bad status
|
return TRUE; // return bad status
|
||||||
@@ -370,7 +370,7 @@ bool scan_monster_precache_cfg(FILE *fp)
|
|||||||
|
|
||||||
if (found == FALSE)
|
if (found == FALSE)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: invalid precache monster name: %s", input);
|
//META_CONS("[MONSTER] ERROR: invalid precache monster name: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: invalid precache monster name: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: invalid precache monster name: %s", input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -397,13 +397,13 @@ bool process_monster_precache_cfg(void)
|
|||||||
{
|
{
|
||||||
if (dllapi_log->value)
|
if (dllapi_log->value)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] Processing config file=%s", filename);
|
//META_CONS("[MONSTER] Processing config file=%s", filename);
|
||||||
LOG_MESSAGE(PLID, "Processing config file=%s", filename);
|
LOG_MESSAGE(PLID, "Processing config file=%s", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fp = fopen(filename, "r")) == NULL)
|
if ((fp = fopen(filename, "r")) == NULL)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename);
|
//META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename);
|
||||||
LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\" file!", filename);
|
LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\" file!", filename);
|
||||||
|
|
||||||
return TRUE; // return bad status
|
return TRUE; // return bad status
|
||||||
|
|||||||
@@ -1629,9 +1629,9 @@ void CMBaseMonster :: MonsterInit ( void )
|
|||||||
// set eye position
|
// set eye position
|
||||||
SetEyePosition();
|
SetEyePosition();
|
||||||
|
|
||||||
SetThink( MonsterInitThink );
|
SetThink( &CMBaseMonster::MonsterInitThink );
|
||||||
pev->nextthink = gpGlobals->time + 0.1;
|
pev->nextthink = gpGlobals->time + 0.1;
|
||||||
SetUse ( MonsterUse );
|
SetUse ( &CMBaseMonster::MonsterUse );
|
||||||
}
|
}
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
@@ -1733,7 +1733,7 @@ void CMBaseMonster :: StartMonster ( void )
|
|||||||
|
|
||||||
// Delay drop to floor to make sure each door in the level has had its chance to spawn
|
// Delay drop to floor to make sure each door in the level has had its chance to spawn
|
||||||
// Spread think times so that they don't all happen at the same time (Carmack)
|
// Spread think times so that they don't all happen at the same time (Carmack)
|
||||||
SetThink ( CallMonsterThink );
|
SetThink ( &CMBaseMonster::CallMonsterThink );
|
||||||
pev->nextthink += RANDOM_FLOAT(0.1, 0.4); // spread think times.
|
pev->nextthink += RANDOM_FLOAT(0.1, 0.4); // spread think times.
|
||||||
|
|
||||||
if ( !FStringNull(pev->targetname) )// wait until triggered
|
if ( !FStringNull(pev->targetname) )// wait until triggered
|
||||||
@@ -2770,7 +2770,7 @@ void CMBaseMonster :: MonsterInitDead( void )
|
|||||||
|
|
||||||
// Setup health counters, etc.
|
// Setup health counters, etc.
|
||||||
BecomeDead();
|
BecomeDead();
|
||||||
SetThink( CorpseFallThink );
|
SetThink( &CMBaseMonster::CorpseFallThink );
|
||||||
pev->nextthink = gpGlobals->time + 0.5;
|
pev->nextthink = gpGlobals->time + 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,13 @@
|
|||||||
#include "animation.h"
|
#include "animation.h"
|
||||||
#include "doors.h"
|
#include "doors.h"
|
||||||
|
|
||||||
|
//#if !defined ( _WIN32 )
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h> // mkdir
|
||||||
|
//#endif
|
||||||
|
|
||||||
#define HULL_STEP_SIZE 16// how far the test hull moves on each step
|
#define HULL_STEP_SIZE 16// how far the test hull moves on each step
|
||||||
#define NODE_HEIGHT 8 // how high to lift nodes off the ground after we drop them all (make stair/ramp mapping easier)
|
#define NODE_HEIGHT 8 // how high to lift nodes off the ground after we drop them all (make stair/ramp mapping easier)
|
||||||
|
|
||||||
@@ -610,7 +617,8 @@ int CGraph :: FindShortestPath ( int *piPath, int iStart, int iDest, int iHull,
|
|||||||
|
|
||||||
// Mark all the nodes as unvisited.
|
// Mark all the nodes as unvisited.
|
||||||
//
|
//
|
||||||
for ( int i = 0; i < m_cNodes; i++)
|
int i;
|
||||||
|
for ( i = 0; i < m_cNodes; i++)
|
||||||
{
|
{
|
||||||
m_pNodes[ i ].m_flClosestSoFar = -1.0;
|
m_pNodes[ i ].m_flClosestSoFar = -1.0;
|
||||||
}
|
}
|
||||||
@@ -1411,12 +1419,12 @@ void CTestHull :: Spawn( entvars_t *pevMasterNode )
|
|||||||
|
|
||||||
if ( WorldGraph.m_fGraphPresent )
|
if ( WorldGraph.m_fGraphPresent )
|
||||||
{// graph loaded from disk, so we don't need the test hull
|
{// graph loaded from disk, so we don't need the test hull
|
||||||
SetThink ( SUB_Remove );
|
SetThink ( &CTestHull::SUB_Remove );
|
||||||
pev->nextthink = gpGlobals->time;
|
pev->nextthink = gpGlobals->time;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetThink ( DropDelay );
|
SetThink ( &CTestHull::DropDelay );
|
||||||
pev->nextthink = gpGlobals->time + 1;
|
pev->nextthink = gpGlobals->time + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1436,7 +1444,7 @@ void CTestHull::DropDelay ( void )
|
|||||||
|
|
||||||
UTIL_SetOrigin ( VARS(pev), WorldGraph.m_pNodes[ 0 ].m_vecOrigin );
|
UTIL_SetOrigin ( VARS(pev), WorldGraph.m_pNodes[ 0 ].m_vecOrigin );
|
||||||
|
|
||||||
SetThink ( CallBuildNodeGraph );
|
SetThink ( &CTestHull::CallBuildNodeGraph );
|
||||||
|
|
||||||
pev->nextthink = gpGlobals->time + 1;
|
pev->nextthink = gpGlobals->time + 1;
|
||||||
}
|
}
|
||||||
@@ -1584,7 +1592,7 @@ void CTestHull :: BuildNodeGraph( void )
|
|||||||
float flDist;
|
float flDist;
|
||||||
int step;
|
int step;
|
||||||
|
|
||||||
SetThink ( SUB_Remove );// no matter what happens, the hull gets rid of itself.
|
SetThink ( &CTestHull::SUB_Remove );// no matter what happens, the hull gets rid of itself.
|
||||||
pev->nextthink = gpGlobals->time;
|
pev->nextthink = gpGlobals->time;
|
||||||
|
|
||||||
// malloc a swollen temporary connection pool that we trim down after we know exactly how many connections there are.
|
// malloc a swollen temporary connection pool that we trim down after we know exactly how many connections there are.
|
||||||
@@ -1696,7 +1704,7 @@ void CTestHull :: BuildNodeGraph( void )
|
|||||||
{
|
{
|
||||||
ALERT ( at_aiconsole, "**ConnectVisibleNodes FAILED!\n" );
|
ALERT ( at_aiconsole, "**ConnectVisibleNodes FAILED!\n" );
|
||||||
|
|
||||||
SetThink ( ShowBadNode );// send the hull off to show the offending node.
|
SetThink ( &CTestHull::ShowBadNode );// send the hull off to show the offending node.
|
||||||
//pev->solid = SOLID_NOT;
|
//pev->solid = SOLID_NOT;
|
||||||
pev->origin = WorldGraph.m_pNodes[ iBadNode ].m_vecOrigin;
|
pev->origin = WorldGraph.m_pNodes[ iBadNode ].m_vecOrigin;
|
||||||
|
|
||||||
@@ -2685,7 +2693,9 @@ void CGraph::HashChoosePrimes(int TableSize)
|
|||||||
// We divide this interval into 16 equal sized zones. We want to find
|
// We divide this interval into 16 equal sized zones. We want to find
|
||||||
// one prime number that best represents that zone.
|
// one prime number that best represents that zone.
|
||||||
//
|
//
|
||||||
for (int iZone = 1, iPrime = 0; iPrime < 16; iZone += Spacing)
|
int iPrime;
|
||||||
|
int iZone;
|
||||||
|
for (iZone = 1, iPrime = 0; iPrime < 16; iZone += Spacing)
|
||||||
{
|
{
|
||||||
// Search for a prime number that is less than the target zone
|
// Search for a prime number that is less than the target zone
|
||||||
// number given by iZone.
|
// number given by iZone.
|
||||||
@@ -2742,8 +2752,9 @@ void CGraph::SortNodes(void)
|
|||||||
// things and patchup the links.
|
// things and patchup the links.
|
||||||
//
|
//
|
||||||
int iNodeCnt = 0;
|
int iNodeCnt = 0;
|
||||||
|
int i;
|
||||||
m_pNodes[0].m_iPreviousNode = iNodeCnt++;
|
m_pNodes[0].m_iPreviousNode = iNodeCnt++;
|
||||||
for (int i = 1; i < m_cNodes; i++)
|
for (i = 1; i < m_cNodes; i++)
|
||||||
{
|
{
|
||||||
m_pNodes[i].m_iPreviousNode = UNNUMBERED_NODE;
|
m_pNodes[i].m_iPreviousNode = UNNUMBERED_NODE;
|
||||||
}
|
}
|
||||||
@@ -2808,7 +2819,8 @@ void CGraph::BuildLinkLookups(void)
|
|||||||
ALERT(at_aiconsole, "Couldn't allocated Link Lookup Table.\n");
|
ALERT(at_aiconsole, "Couldn't allocated Link Lookup Table.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < m_nHashLinks; i++)
|
int i;
|
||||||
|
for (i = 0; i < m_nHashLinks; i++)
|
||||||
{
|
{
|
||||||
m_pHashLinks[i] = ENTRY_STATE_EMPTY;
|
m_pHashLinks[i] = ENTRY_STATE_EMPTY;
|
||||||
}
|
}
|
||||||
@@ -2848,7 +2860,8 @@ void CGraph::BuildRegionTables(void)
|
|||||||
// Calculate regions for all the nodes.
|
// Calculate regions for all the nodes.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
for (int i = 0; i < 3; i++)
|
int i;
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
m_RegionMin[i] = 999999999.0; // just a big number out there;
|
m_RegionMin[i] = 999999999.0; // just a big number out there;
|
||||||
m_RegionMax[i] = -999999999.0; // just a big number out there;
|
m_RegionMax[i] = -999999999.0; // just a big number out there;
|
||||||
@@ -2878,7 +2891,8 @@ void CGraph::BuildRegionTables(void)
|
|||||||
|
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < NUM_RANGES; j++)
|
int j;
|
||||||
|
for (j = 0; j < NUM_RANGES; j++)
|
||||||
{
|
{
|
||||||
m_RangeStart[i][j] = 255;
|
m_RangeStart[i][j] = 255;
|
||||||
m_RangeEnd[i][j] = 0;
|
m_RangeEnd[i][j] = 0;
|
||||||
@@ -3012,7 +3026,8 @@ void CGraph :: ComputeStaticRoutingTables( void )
|
|||||||
|
|
||||||
// Initialize Routing table to uncalculated.
|
// Initialize Routing table to uncalculated.
|
||||||
//
|
//
|
||||||
for (int iFrom = 0; iFrom < m_cNodes; iFrom++)
|
int iFrom;
|
||||||
|
for (iFrom = 0; iFrom < m_cNodes; iFrom++)
|
||||||
{
|
{
|
||||||
for (int iTo = 0; iTo < m_cNodes; iTo++)
|
for (int iTo = 0; iTo < m_cNodes; iTo++)
|
||||||
{
|
{
|
||||||
@@ -3228,7 +3243,8 @@ void CGraph :: ComputeStaticRoutingTables( void )
|
|||||||
int nRoute = p - pRoute;
|
int nRoute = p - pRoute;
|
||||||
if (m_pRouteInfo)
|
if (m_pRouteInfo)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_nRouteInfo - nRoute; i++)
|
int i;
|
||||||
|
for (i = 0; i < m_nRouteInfo - nRoute; i++)
|
||||||
{
|
{
|
||||||
if (memcmp(m_pRouteInfo + i, pRoute, nRoute) == 0)
|
if (memcmp(m_pRouteInfo + i, pRoute, nRoute) == 0)
|
||||||
{
|
{
|
||||||
@@ -3320,7 +3336,8 @@ void CGraph :: TestRoutingTables( void )
|
|||||||
//
|
//
|
||||||
#if 1
|
#if 1
|
||||||
float flDistance1 = 0.0;
|
float flDistance1 = 0.0;
|
||||||
for (int i = 0; i < cPathSize1-1; i++)
|
int i;
|
||||||
|
for (i = 0; i < cPathSize1-1; i++)
|
||||||
{
|
{
|
||||||
// Find the link from pMyPath[i] to pMyPath[i+1]
|
// Find the link from pMyPath[i] to pMyPath[i+1]
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ void scan_monster_skill(FILE *fp)
|
|||||||
|
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: unknown monster_skill.cfg item: %s", input);
|
//META_CONS("[MONSTER] ERROR: unknown monster_skill.cfg item: %s", input);
|
||||||
LOG_MESSAGE(PLID, "ERROR: unknown monster_skill.cfg item: %s", input);
|
LOG_MESSAGE(PLID, "ERROR: unknown monster_skill.cfg item: %s", input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,13 +231,13 @@ void monster_skill_init(void)
|
|||||||
{
|
{
|
||||||
if (dllapi_log->value)
|
if (dllapi_log->value)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] Processing monster skill file=%s", filename);
|
//META_CONS("[MONSTER] Processing monster skill file=%s", filename);
|
||||||
LOG_MESSAGE(PLID, "Processing monster skill file=%s", filename);
|
LOG_MESSAGE(PLID, "Processing monster skill file=%s", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((fp = fopen(filename, "r")) == NULL)
|
if ((fp = fopen(filename, "r")) == NULL)
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename);
|
//META_CONS("[MONSTER] ERROR: Could not open \"%s\"!", filename);
|
||||||
LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\"!", filename);
|
LOG_MESSAGE(PLID, "ERROR: Could not open \"%s\"!", filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +247,7 @@ void monster_skill_init(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
META_CONS("[MONSTER] ERROR: Could not find \"%s\" (default skill used)", filename);
|
//META_CONS("[MONSTER] ERROR: Could not find \"%s\" (default skill used)", filename);
|
||||||
LOG_MESSAGE(PLID, "ERROR: Could not find \"%s\" (default skill used)", filename);
|
LOG_MESSAGE(PLID, "ERROR: Could not find \"%s\" (default skill used)", filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,9 @@
|
|||||||
#include "cmtalkmonster.h"
|
#include "cmtalkmonster.h"
|
||||||
#include "pm_materials.h"
|
#include "pm_materials.h"
|
||||||
|
|
||||||
|
//#if !defined ( _WIN32 )
|
||||||
|
#include <ctype.h>
|
||||||
|
//#endif
|
||||||
|
|
||||||
static char *memfgets( byte *pMemFile, int fileSize, int &filePos, char *pBuffer, int bufferSize );
|
static char *memfgets( byte *pMemFile, int fileSize, int &filePos, char *pBuffer, int bufferSize );
|
||||||
|
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ void CMSqueakGrenade :: Spawn( void )
|
|||||||
UTIL_SetSize(pev, Vector( -4, -4, 0), Vector(4, 4, 8));
|
UTIL_SetSize(pev, Vector( -4, -4, 0), Vector(4, 4, 8));
|
||||||
UTIL_SetOrigin( pev, pev->origin );
|
UTIL_SetOrigin( pev, pev->origin );
|
||||||
|
|
||||||
SetTouch( SuperBounceTouch );
|
SetTouch( &CMSqueakGrenade::SuperBounceTouch );
|
||||||
SetThink( HuntThink );
|
SetThink( &CMSqueakGrenade::HuntThink );
|
||||||
pev->nextthink = gpGlobals->time + 0.1;
|
pev->nextthink = gpGlobals->time + 0.1;
|
||||||
m_flNextHunt = gpGlobals->time + 1E6;
|
m_flNextHunt = gpGlobals->time + 1E6;
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ void CMSqueakGrenade::Precache( void )
|
|||||||
void CMSqueakGrenade :: Killed( entvars_t *pevAttacker, int iGib )
|
void CMSqueakGrenade :: Killed( entvars_t *pevAttacker, int iGib )
|
||||||
{
|
{
|
||||||
pev->model = iStringNull;// make invisible
|
pev->model = iStringNull;// make invisible
|
||||||
SetThink( SUB_Remove );
|
SetThink( &CMSqueakGrenade::SUB_Remove );
|
||||||
SetTouch( NULL );
|
SetTouch( NULL );
|
||||||
pev->nextthink = gpGlobals->time + 0.1;
|
pev->nextthink = gpGlobals->time + 0.1;
|
||||||
|
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ void CMBaseDelay :: SUB_UseTargets( edict_t *pActivator, USE_TYPE useType, float
|
|||||||
|
|
||||||
pTemp->pev->nextthink = gpGlobals->time + m_flDelay;
|
pTemp->pev->nextthink = gpGlobals->time + m_flDelay;
|
||||||
|
|
||||||
pTemp->SetThink( DelayThink );
|
pTemp->SetThink( &CMBaseDelay::DelayThink );
|
||||||
|
|
||||||
// Save the useType
|
// Save the useType
|
||||||
pTemp->pev->button = (int)useType;
|
pTemp->pev->button = (int)useType;
|
||||||
@@ -327,7 +327,7 @@ void CMBaseToggle :: LinearMove( Vector vecDest, float flSpeed )
|
|||||||
|
|
||||||
// set nextthink to trigger a call to LinearMoveDone when dest is reached
|
// set nextthink to trigger a call to LinearMoveDone when dest is reached
|
||||||
pev->nextthink = pev->ltime + flTravelTime;
|
pev->nextthink = pev->ltime + flTravelTime;
|
||||||
SetThink( LinearMoveDone );
|
SetThink( &CMBaseToggle::LinearMoveDone );
|
||||||
|
|
||||||
// scale the destdelta vector by the time spent traveling to get velocity
|
// scale the destdelta vector by the time spent traveling to get velocity
|
||||||
pev->velocity = vecDestDelta / flTravelTime;
|
pev->velocity = vecDestDelta / flTravelTime;
|
||||||
@@ -384,7 +384,7 @@ void CMBaseToggle :: AngularMove( Vector vecDestAngle, float flSpeed )
|
|||||||
|
|
||||||
// set nextthink to trigger a call to AngularMoveDone when dest is reached
|
// set nextthink to trigger a call to AngularMoveDone when dest is reached
|
||||||
pev->nextthink = pev->ltime + flTravelTime;
|
pev->nextthink = pev->ltime + flTravelTime;
|
||||||
SetThink( AngularMoveDone );
|
SetThink( &CMBaseToggle::AngularMoveDone );
|
||||||
|
|
||||||
// scale the destdelta vector by the time spent traveling to get velocity
|
// scale the destdelta vector by the time spent traveling to get velocity
|
||||||
pev->avelocity = vecDestDelta / flTravelTime;
|
pev->avelocity = vecDestDelta / flTravelTime;
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ typedef enum
|
|||||||
} TOGGLE_STATE;
|
} TOGGLE_STATE;
|
||||||
|
|
||||||
// Misc useful
|
// Misc useful
|
||||||
|
#include "string.h"
|
||||||
inline BOOL FStrEq(const char*sz1, const char*sz2)
|
inline BOOL FStrEq(const char*sz1, const char*sz2)
|
||||||
{ return (strcmp(sz1, sz2) == 0); }
|
{ return (strcmp(sz1, sz2) == 0); }
|
||||||
inline BOOL FClassnameIs(edict_t* pent, const char* szClassname)
|
inline BOOL FClassnameIs(edict_t* pent, const char* szClassname)
|
||||||
|
|||||||
201
src/engine/Sequence.h
Normal file
201
src/engine/Sequence.h
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
//---------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// S c r i p t e d S e q u e n c e s
|
||||||
|
//
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
#ifndef _INCLUDE_SEQUENCE_H_
|
||||||
|
#define _INCLUDE_SEQUENCE_H_
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _DEF_BYTE_
|
||||||
|
typedef unsigned char byte;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// client_textmessage_t
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
typedef struct client_textmessage_s
|
||||||
|
{
|
||||||
|
int effect;
|
||||||
|
byte r1, g1, b1, a1; // 2 colors for effects
|
||||||
|
byte r2, g2, b2, a2;
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float fadein;
|
||||||
|
float fadeout;
|
||||||
|
float holdtime;
|
||||||
|
float fxtime;
|
||||||
|
const char *pName;
|
||||||
|
const char *pMessage;
|
||||||
|
} client_textmessage_t;
|
||||||
|
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// sequenceDefaultBits_e
|
||||||
|
//
|
||||||
|
// Enumerated list of possible modifiers for a command. This enumeration
|
||||||
|
// is used in a bitarray controlling what modifiers are specified for a command.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
enum sequenceModifierBits
|
||||||
|
{
|
||||||
|
SEQUENCE_MODIFIER_EFFECT_BIT = (1 << 1),
|
||||||
|
SEQUENCE_MODIFIER_POSITION_BIT = (1 << 2),
|
||||||
|
SEQUENCE_MODIFIER_COLOR_BIT = (1 << 3),
|
||||||
|
SEQUENCE_MODIFIER_COLOR2_BIT = (1 << 4),
|
||||||
|
SEQUENCE_MODIFIER_FADEIN_BIT = (1 << 5),
|
||||||
|
SEQUENCE_MODIFIER_FADEOUT_BIT = (1 << 6),
|
||||||
|
SEQUENCE_MODIFIER_HOLDTIME_BIT = (1 << 7),
|
||||||
|
SEQUENCE_MODIFIER_FXTIME_BIT = (1 << 8),
|
||||||
|
SEQUENCE_MODIFIER_SPEAKER_BIT = (1 << 9),
|
||||||
|
SEQUENCE_MODIFIER_LISTENER_BIT = (1 << 10),
|
||||||
|
SEQUENCE_MODIFIER_TEXTCHANNEL_BIT = (1 << 11),
|
||||||
|
};
|
||||||
|
typedef enum sequenceModifierBits sequenceModifierBits_e ;
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// sequenceCommandEnum_e
|
||||||
|
//
|
||||||
|
// Enumerated sequence command types.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
enum sequenceCommandEnum_
|
||||||
|
{
|
||||||
|
SEQUENCE_COMMAND_ERROR = -1,
|
||||||
|
SEQUENCE_COMMAND_PAUSE = 0,
|
||||||
|
SEQUENCE_COMMAND_FIRETARGETS,
|
||||||
|
SEQUENCE_COMMAND_KILLTARGETS,
|
||||||
|
SEQUENCE_COMMAND_TEXT,
|
||||||
|
SEQUENCE_COMMAND_SOUND,
|
||||||
|
SEQUENCE_COMMAND_GOSUB,
|
||||||
|
SEQUENCE_COMMAND_SENTENCE,
|
||||||
|
SEQUENCE_COMMAND_REPEAT,
|
||||||
|
SEQUENCE_COMMAND_SETDEFAULTS,
|
||||||
|
SEQUENCE_COMMAND_MODIFIER,
|
||||||
|
SEQUENCE_COMMAND_POSTMODIFIER,
|
||||||
|
SEQUENCE_COMMAND_NOOP,
|
||||||
|
|
||||||
|
SEQUENCE_MODIFIER_EFFECT,
|
||||||
|
SEQUENCE_MODIFIER_POSITION,
|
||||||
|
SEQUENCE_MODIFIER_COLOR,
|
||||||
|
SEQUENCE_MODIFIER_COLOR2,
|
||||||
|
SEQUENCE_MODIFIER_FADEIN,
|
||||||
|
SEQUENCE_MODIFIER_FADEOUT,
|
||||||
|
SEQUENCE_MODIFIER_HOLDTIME,
|
||||||
|
SEQUENCE_MODIFIER_FXTIME,
|
||||||
|
SEQUENCE_MODIFIER_SPEAKER,
|
||||||
|
SEQUENCE_MODIFIER_LISTENER,
|
||||||
|
SEQUENCE_MODIFIER_TEXTCHANNEL,
|
||||||
|
};
|
||||||
|
typedef enum sequenceCommandEnum_ sequenceCommandEnum_e;
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// sequenceCommandType_e
|
||||||
|
//
|
||||||
|
// Typeerated sequence command types.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
enum sequenceCommandType_
|
||||||
|
{
|
||||||
|
SEQUENCE_TYPE_COMMAND,
|
||||||
|
SEQUENCE_TYPE_MODIFIER,
|
||||||
|
};
|
||||||
|
typedef enum sequenceCommandType_ sequenceCommandType_e;
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// sequenceCommandMapping_s
|
||||||
|
//
|
||||||
|
// A mapping of a command enumerated-value to its name.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
typedef struct sequenceCommandMapping_ sequenceCommandMapping_s;
|
||||||
|
struct sequenceCommandMapping_
|
||||||
|
{
|
||||||
|
sequenceCommandEnum_e commandEnum;
|
||||||
|
const char* commandName;
|
||||||
|
sequenceCommandType_e commandType;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// sequenceCommandLine_s
|
||||||
|
//
|
||||||
|
// Structure representing a single command (usually 1 line) from a
|
||||||
|
// .SEQ file entry.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
typedef struct sequenceCommandLine_ sequenceCommandLine_s;
|
||||||
|
struct sequenceCommandLine_
|
||||||
|
{
|
||||||
|
int commandType; // Specifies the type of command
|
||||||
|
client_textmessage_t clientMessage; // Text HUD message struct
|
||||||
|
char* speakerName; // Targetname of speaking entity
|
||||||
|
char* listenerName; // Targetname of entity being spoken to
|
||||||
|
char* soundFileName; // Name of sound file to play
|
||||||
|
char* sentenceName; // Name of sentences.txt to play
|
||||||
|
char* fireTargetNames; // List of targetnames to fire
|
||||||
|
char* killTargetNames; // List of targetnames to remove
|
||||||
|
float delay; // Seconds 'till next command
|
||||||
|
int repeatCount; // If nonzero, reset execution pointer to top of block (N times, -1 = infinite)
|
||||||
|
int textChannel; // Display channel on which text message is sent
|
||||||
|
int modifierBitField; // Bit field to specify what clientmessage fields are valid
|
||||||
|
sequenceCommandLine_s* nextCommandLine; // Next command (linked list)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// sequenceEntry_s
|
||||||
|
//
|
||||||
|
// Structure representing a single command (usually 1 line) from a
|
||||||
|
// .SEQ file entry.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
typedef struct sequenceEntry_ sequenceEntry_s;
|
||||||
|
struct sequenceEntry_
|
||||||
|
{
|
||||||
|
char* fileName; // Name of sequence file without .SEQ extension
|
||||||
|
char* entryName; // Name of entry label in file
|
||||||
|
sequenceCommandLine_s* firstCommand; // Linked list of commands in entry
|
||||||
|
sequenceEntry_s* nextEntry; // Next loaded entry
|
||||||
|
qboolean isGlobal; // Is entry retained over level transitions?
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// sentenceEntry_s
|
||||||
|
// Structure representing a single sentence of a group from a .SEQ
|
||||||
|
// file entry. Sentences are identical to entries in sentences.txt, but
|
||||||
|
// can be unique per level and are loaded/unloaded with the level.
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
typedef struct sentenceEntry_ sentenceEntry_s;
|
||||||
|
struct sentenceEntry_
|
||||||
|
{
|
||||||
|
char* data; // sentence data (ie "We have hostiles" )
|
||||||
|
sentenceEntry_s* nextEntry; // Next loaded entry
|
||||||
|
qboolean isGlobal; // Is entry retained over level transitions?
|
||||||
|
unsigned int index; // this entry's position in the file.
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// sentenceGroupEntry_s
|
||||||
|
// Structure representing a group of sentences found in a .SEQ file.
|
||||||
|
// A sentence group is defined by all sentences with the same name, ignoring
|
||||||
|
// the number at the end of the sentence name. Groups enable a sentence
|
||||||
|
// to be picked at random across a group.
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
typedef struct sentenceGroupEntry_ sentenceGroupEntry_s;
|
||||||
|
struct sentenceGroupEntry_
|
||||||
|
{
|
||||||
|
char* groupName; // name of the group (ie CT_ALERT )
|
||||||
|
unsigned int numSentences; // number of sentences in group
|
||||||
|
sentenceEntry_s* firstSentence; // head of linked list of sentences in group
|
||||||
|
sentenceGroupEntry_s* nextEntry; // next loaded group
|
||||||
|
};
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
// Function declarations
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
sequenceEntry_s* SequenceGet( const char* fileName, const char* entryName );
|
||||||
|
void Sequence_ParseFile( const char* fileName, qboolean isGlobal );
|
||||||
|
void Sequence_OnLevelLoad( const char* mapName );
|
||||||
|
sentenceEntry_s* SequencePickSentence( const char *groupName, int pickMethod, int *picked );
|
||||||
|
|
||||||
|
#endif /* _INCLUDE_SEQUENCE_H_ */
|
||||||
177
src/engine/anorms.h
Normal file
177
src/engine/anorms.h
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
/***
|
||||||
|
*
|
||||||
|
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||||
|
*
|
||||||
|
* This product contains software technology licensed from Id
|
||||||
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use, distribution, and modification of this source code and/or resulting
|
||||||
|
* object code is restricted to non-commercial enhancements to products from
|
||||||
|
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||||
|
* without written permission from Valve LLC.
|
||||||
|
*
|
||||||
|
****/
|
||||||
|
|
||||||
|
{-0.525731, 0.000000, 0.850651},
|
||||||
|
{-0.442863, 0.238856, 0.864188},
|
||||||
|
{-0.295242, 0.000000, 0.955423},
|
||||||
|
{-0.309017, 0.500000, 0.809017},
|
||||||
|
{-0.162460, 0.262866, 0.951056},
|
||||||
|
{0.000000, 0.000000, 1.000000},
|
||||||
|
{0.000000, 0.850651, 0.525731},
|
||||||
|
{-0.147621, 0.716567, 0.681718},
|
||||||
|
{0.147621, 0.716567, 0.681718},
|
||||||
|
{0.000000, 0.525731, 0.850651},
|
||||||
|
{0.309017, 0.500000, 0.809017},
|
||||||
|
{0.525731, 0.000000, 0.850651},
|
||||||
|
{0.295242, 0.000000, 0.955423},
|
||||||
|
{0.442863, 0.238856, 0.864188},
|
||||||
|
{0.162460, 0.262866, 0.951056},
|
||||||
|
{-0.681718, 0.147621, 0.716567},
|
||||||
|
{-0.809017, 0.309017, 0.500000},
|
||||||
|
{-0.587785, 0.425325, 0.688191},
|
||||||
|
{-0.850651, 0.525731, 0.000000},
|
||||||
|
{-0.864188, 0.442863, 0.238856},
|
||||||
|
{-0.716567, 0.681718, 0.147621},
|
||||||
|
{-0.688191, 0.587785, 0.425325},
|
||||||
|
{-0.500000, 0.809017, 0.309017},
|
||||||
|
{-0.238856, 0.864188, 0.442863},
|
||||||
|
{-0.425325, 0.688191, 0.587785},
|
||||||
|
{-0.716567, 0.681718, -0.147621},
|
||||||
|
{-0.500000, 0.809017, -0.309017},
|
||||||
|
{-0.525731, 0.850651, 0.000000},
|
||||||
|
{0.000000, 0.850651, -0.525731},
|
||||||
|
{-0.238856, 0.864188, -0.442863},
|
||||||
|
{0.000000, 0.955423, -0.295242},
|
||||||
|
{-0.262866, 0.951056, -0.162460},
|
||||||
|
{0.000000, 1.000000, 0.000000},
|
||||||
|
{0.000000, 0.955423, 0.295242},
|
||||||
|
{-0.262866, 0.951056, 0.162460},
|
||||||
|
{0.238856, 0.864188, 0.442863},
|
||||||
|
{0.262866, 0.951056, 0.162460},
|
||||||
|
{0.500000, 0.809017, 0.309017},
|
||||||
|
{0.238856, 0.864188, -0.442863},
|
||||||
|
{0.262866, 0.951056, -0.162460},
|
||||||
|
{0.500000, 0.809017, -0.309017},
|
||||||
|
{0.850651, 0.525731, 0.000000},
|
||||||
|
{0.716567, 0.681718, 0.147621},
|
||||||
|
{0.716567, 0.681718, -0.147621},
|
||||||
|
{0.525731, 0.850651, 0.000000},
|
||||||
|
{0.425325, 0.688191, 0.587785},
|
||||||
|
{0.864188, 0.442863, 0.238856},
|
||||||
|
{0.688191, 0.587785, 0.425325},
|
||||||
|
{0.809017, 0.309017, 0.500000},
|
||||||
|
{0.681718, 0.147621, 0.716567},
|
||||||
|
{0.587785, 0.425325, 0.688191},
|
||||||
|
{0.955423, 0.295242, 0.000000},
|
||||||
|
{1.000000, 0.000000, 0.000000},
|
||||||
|
{0.951056, 0.162460, 0.262866},
|
||||||
|
{0.850651, -0.525731, 0.000000},
|
||||||
|
{0.955423, -0.295242, 0.000000},
|
||||||
|
{0.864188, -0.442863, 0.238856},
|
||||||
|
{0.951056, -0.162460, 0.262866},
|
||||||
|
{0.809017, -0.309017, 0.500000},
|
||||||
|
{0.681718, -0.147621, 0.716567},
|
||||||
|
{0.850651, 0.000000, 0.525731},
|
||||||
|
{0.864188, 0.442863, -0.238856},
|
||||||
|
{0.809017, 0.309017, -0.500000},
|
||||||
|
{0.951056, 0.162460, -0.262866},
|
||||||
|
{0.525731, 0.000000, -0.850651},
|
||||||
|
{0.681718, 0.147621, -0.716567},
|
||||||
|
{0.681718, -0.147621, -0.716567},
|
||||||
|
{0.850651, 0.000000, -0.525731},
|
||||||
|
{0.809017, -0.309017, -0.500000},
|
||||||
|
{0.864188, -0.442863, -0.238856},
|
||||||
|
{0.951056, -0.162460, -0.262866},
|
||||||
|
{0.147621, 0.716567, -0.681718},
|
||||||
|
{0.309017, 0.500000, -0.809017},
|
||||||
|
{0.425325, 0.688191, -0.587785},
|
||||||
|
{0.442863, 0.238856, -0.864188},
|
||||||
|
{0.587785, 0.425325, -0.688191},
|
||||||
|
{0.688191, 0.587785, -0.425325},
|
||||||
|
{-0.147621, 0.716567, -0.681718},
|
||||||
|
{-0.309017, 0.500000, -0.809017},
|
||||||
|
{0.000000, 0.525731, -0.850651},
|
||||||
|
{-0.525731, 0.000000, -0.850651},
|
||||||
|
{-0.442863, 0.238856, -0.864188},
|
||||||
|
{-0.295242, 0.000000, -0.955423},
|
||||||
|
{-0.162460, 0.262866, -0.951056},
|
||||||
|
{0.000000, 0.000000, -1.000000},
|
||||||
|
{0.295242, 0.000000, -0.955423},
|
||||||
|
{0.162460, 0.262866, -0.951056},
|
||||||
|
{-0.442863, -0.238856, -0.864188},
|
||||||
|
{-0.309017, -0.500000, -0.809017},
|
||||||
|
{-0.162460, -0.262866, -0.951056},
|
||||||
|
{0.000000, -0.850651, -0.525731},
|
||||||
|
{-0.147621, -0.716567, -0.681718},
|
||||||
|
{0.147621, -0.716567, -0.681718},
|
||||||
|
{0.000000, -0.525731, -0.850651},
|
||||||
|
{0.309017, -0.500000, -0.809017},
|
||||||
|
{0.442863, -0.238856, -0.864188},
|
||||||
|
{0.162460, -0.262866, -0.951056},
|
||||||
|
{0.238856, -0.864188, -0.442863},
|
||||||
|
{0.500000, -0.809017, -0.309017},
|
||||||
|
{0.425325, -0.688191, -0.587785},
|
||||||
|
{0.716567, -0.681718, -0.147621},
|
||||||
|
{0.688191, -0.587785, -0.425325},
|
||||||
|
{0.587785, -0.425325, -0.688191},
|
||||||
|
{0.000000, -0.955423, -0.295242},
|
||||||
|
{0.000000, -1.000000, 0.000000},
|
||||||
|
{0.262866, -0.951056, -0.162460},
|
||||||
|
{0.000000, -0.850651, 0.525731},
|
||||||
|
{0.000000, -0.955423, 0.295242},
|
||||||
|
{0.238856, -0.864188, 0.442863},
|
||||||
|
{0.262866, -0.951056, 0.162460},
|
||||||
|
{0.500000, -0.809017, 0.309017},
|
||||||
|
{0.716567, -0.681718, 0.147621},
|
||||||
|
{0.525731, -0.850651, 0.000000},
|
||||||
|
{-0.238856, -0.864188, -0.442863},
|
||||||
|
{-0.500000, -0.809017, -0.309017},
|
||||||
|
{-0.262866, -0.951056, -0.162460},
|
||||||
|
{-0.850651, -0.525731, 0.000000},
|
||||||
|
{-0.716567, -0.681718, -0.147621},
|
||||||
|
{-0.716567, -0.681718, 0.147621},
|
||||||
|
{-0.525731, -0.850651, 0.000000},
|
||||||
|
{-0.500000, -0.809017, 0.309017},
|
||||||
|
{-0.238856, -0.864188, 0.442863},
|
||||||
|
{-0.262866, -0.951056, 0.162460},
|
||||||
|
{-0.864188, -0.442863, 0.238856},
|
||||||
|
{-0.809017, -0.309017, 0.500000},
|
||||||
|
{-0.688191, -0.587785, 0.425325},
|
||||||
|
{-0.681718, -0.147621, 0.716567},
|
||||||
|
{-0.442863, -0.238856, 0.864188},
|
||||||
|
{-0.587785, -0.425325, 0.688191},
|
||||||
|
{-0.309017, -0.500000, 0.809017},
|
||||||
|
{-0.147621, -0.716567, 0.681718},
|
||||||
|
{-0.425325, -0.688191, 0.587785},
|
||||||
|
{-0.162460, -0.262866, 0.951056},
|
||||||
|
{0.442863, -0.238856, 0.864188},
|
||||||
|
{0.162460, -0.262866, 0.951056},
|
||||||
|
{0.309017, -0.500000, 0.809017},
|
||||||
|
{0.147621, -0.716567, 0.681718},
|
||||||
|
{0.000000, -0.525731, 0.850651},
|
||||||
|
{0.425325, -0.688191, 0.587785},
|
||||||
|
{0.587785, -0.425325, 0.688191},
|
||||||
|
{0.688191, -0.587785, 0.425325},
|
||||||
|
{-0.955423, 0.295242, 0.000000},
|
||||||
|
{-0.951056, 0.162460, 0.262866},
|
||||||
|
{-1.000000, 0.000000, 0.000000},
|
||||||
|
{-0.850651, 0.000000, 0.525731},
|
||||||
|
{-0.955423, -0.295242, 0.000000},
|
||||||
|
{-0.951056, -0.162460, 0.262866},
|
||||||
|
{-0.864188, 0.442863, -0.238856},
|
||||||
|
{-0.951056, 0.162460, -0.262866},
|
||||||
|
{-0.809017, 0.309017, -0.500000},
|
||||||
|
{-0.864188, -0.442863, -0.238856},
|
||||||
|
{-0.951056, -0.162460, -0.262866},
|
||||||
|
{-0.809017, -0.309017, -0.500000},
|
||||||
|
{-0.681718, 0.147621, -0.716567},
|
||||||
|
{-0.681718, -0.147621, -0.716567},
|
||||||
|
{-0.850651, 0.000000, -0.525731},
|
||||||
|
{-0.688191, 0.587785, -0.425325},
|
||||||
|
{-0.587785, 0.425325, -0.688191},
|
||||||
|
{-0.425325, 0.688191, -0.587785},
|
||||||
|
{-0.425325, -0.688191, -0.587785},
|
||||||
|
{-0.587785, -0.425325, -0.688191},
|
||||||
|
{-0.688191, -0.587785, -0.425325},
|
||||||
41
src/engine/archtypes.h
Normal file
41
src/engine/archtypes.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// Word size dependent definitions
|
||||||
|
// DAL 1/03
|
||||||
|
//
|
||||||
|
#ifndef ARCHTYPES_H
|
||||||
|
#define ARCHTYPES_H
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
#define X64BITS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined( _WIN32 ) && (! defined( __MINGW32__ ))
|
||||||
|
|
||||||
|
typedef __int16 int16;
|
||||||
|
typedef unsigned __int16 uint16;
|
||||||
|
typedef __int32 int32;
|
||||||
|
typedef unsigned __int32 uint32;
|
||||||
|
typedef __int64 int64;
|
||||||
|
typedef unsigned __int64 uint64;
|
||||||
|
typedef __int32 intp; // intp is an integer that can accomodate a pointer
|
||||||
|
typedef unsigned __int32 uintp; // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *)
|
||||||
|
|
||||||
|
#else /* _WIN32 */
|
||||||
|
|
||||||
|
typedef short int16;
|
||||||
|
typedef unsigned short uint16;
|
||||||
|
typedef int int32;
|
||||||
|
typedef unsigned int uint32;
|
||||||
|
typedef long long int64;
|
||||||
|
typedef unsigned long long uint64;
|
||||||
|
#ifdef X64BITS
|
||||||
|
typedef long long intp;
|
||||||
|
typedef unsigned long long uintp;
|
||||||
|
#else
|
||||||
|
typedef int intp;
|
||||||
|
typedef unsigned int uintp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* else _WIN32 */
|
||||||
|
|
||||||
|
#endif /* ARCHTYPES_H */
|
||||||
311
src/engine/cdll_int.h
Normal file
311
src/engine/cdll_int.h
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
/***
|
||||||
|
*
|
||||||
|
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||||
|
*
|
||||||
|
* This product contains software technology licensed from Id
|
||||||
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use, distribution, and modification of this source code and/or resulting
|
||||||
|
* object code is restricted to non-commercial enhancements to products from
|
||||||
|
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||||
|
* without written permission from Valve LLC.
|
||||||
|
*
|
||||||
|
****/
|
||||||
|
//
|
||||||
|
// cdll_int.h
|
||||||
|
//
|
||||||
|
// 4-23-98
|
||||||
|
// JOHN: client dll interface declarations
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef CDLL_INT_H
|
||||||
|
#define CDLL_INT_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "const.h"
|
||||||
|
|
||||||
|
|
||||||
|
// this file is included by both the engine and the client-dll,
|
||||||
|
// so make sure engine declarations aren't done twice
|
||||||
|
|
||||||
|
typedef int HSPRITE; // handle to a graphic
|
||||||
|
|
||||||
|
#define SCRINFO_SCREENFLASH 1
|
||||||
|
#define SCRINFO_STRETCHED 2
|
||||||
|
|
||||||
|
typedef struct SCREENINFO_s
|
||||||
|
{
|
||||||
|
int iSize;
|
||||||
|
int iWidth;
|
||||||
|
int iHeight;
|
||||||
|
int iFlags;
|
||||||
|
int iCharHeight;
|
||||||
|
short charWidths[256];
|
||||||
|
} SCREENINFO;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct client_data_s
|
||||||
|
{
|
||||||
|
// fields that cannot be modified (ie. have no effect if changed)
|
||||||
|
vec3_t origin;
|
||||||
|
|
||||||
|
// fields that can be changed by the cldll
|
||||||
|
vec3_t viewangles;
|
||||||
|
int iWeaponBits;
|
||||||
|
float fov; // field of view
|
||||||
|
} client_data_t;
|
||||||
|
|
||||||
|
typedef struct client_sprite_s
|
||||||
|
{
|
||||||
|
char szName[64];
|
||||||
|
char szSprite[64];
|
||||||
|
int hspr;
|
||||||
|
int iRes;
|
||||||
|
wrect_t rc;
|
||||||
|
} client_sprite_t;
|
||||||
|
|
||||||
|
typedef struct client_textmessage_s
|
||||||
|
{
|
||||||
|
int effect;
|
||||||
|
byte r1, g1, b1, a1; // 2 colors for effects
|
||||||
|
byte r2, g2, b2, a2;
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float fadein;
|
||||||
|
float fadeout;
|
||||||
|
float holdtime;
|
||||||
|
float fxtime;
|
||||||
|
const char *pName;
|
||||||
|
const char *pMessage;
|
||||||
|
} client_textmessage_t;
|
||||||
|
|
||||||
|
typedef struct hud_player_info_s
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
short ping;
|
||||||
|
byte thisplayer; // TRUE if this is the calling player
|
||||||
|
|
||||||
|
// stuff that's unused at the moment, but should be done
|
||||||
|
byte spectator;
|
||||||
|
byte packetloss;
|
||||||
|
|
||||||
|
char *model;
|
||||||
|
short topcolor;
|
||||||
|
short bottomcolor;
|
||||||
|
|
||||||
|
} hud_player_info_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct cl_enginefuncs_s
|
||||||
|
{
|
||||||
|
// sprite handlers
|
||||||
|
HSPRITE ( *pfnSPR_Load ) ( const char *szPicName );
|
||||||
|
int ( *pfnSPR_Frames ) ( HSPRITE hPic );
|
||||||
|
int ( *pfnSPR_Height ) ( HSPRITE hPic, int frame );
|
||||||
|
int ( *pfnSPR_Width ) ( HSPRITE hPic, int frame );
|
||||||
|
void ( *pfnSPR_Set ) ( HSPRITE hPic, int r, int g, int b );
|
||||||
|
void ( *pfnSPR_Draw ) ( int frame, int x, int y, const wrect_t *prc );
|
||||||
|
void ( *pfnSPR_DrawHoles ) ( int frame, int x, int y, const wrect_t *prc );
|
||||||
|
void ( *pfnSPR_DrawAdditive ) ( int frame, int x, int y, const wrect_t *prc );
|
||||||
|
void ( *pfnSPR_EnableScissor ) ( int x, int y, int width, int height );
|
||||||
|
void ( *pfnSPR_DisableScissor ) ( void );
|
||||||
|
client_sprite_t *( *pfnSPR_GetList ) ( char *psz, int *piCount );
|
||||||
|
|
||||||
|
// screen handlers
|
||||||
|
void ( *pfnFillRGBA ) ( int x, int y, int width, int height, int r, int g, int b, int a );
|
||||||
|
int ( *pfnGetScreenInfo ) ( SCREENINFO *pscrinfo );
|
||||||
|
void ( *pfnSetCrosshair ) ( HSPRITE hspr, wrect_t rc, int r, int g, int b );
|
||||||
|
|
||||||
|
// cvar handlers
|
||||||
|
struct cvar_s *( *pfnRegisterVariable ) ( char *szName, char *szValue, int flags );
|
||||||
|
float ( *pfnGetCvarFloat ) ( char *szName );
|
||||||
|
char* ( *pfnGetCvarString ) ( char *szName );
|
||||||
|
|
||||||
|
// command handlers
|
||||||
|
int ( *pfnAddCommand ) ( char *cmd_name, void (*function)(void) );
|
||||||
|
int ( *pfnHookUserMsg ) ( char *szMsgName, pfnUserMsgHook pfn );
|
||||||
|
int ( *pfnServerCmd ) ( char *szCmdString );
|
||||||
|
int ( *pfnClientCmd ) ( char *szCmdString );
|
||||||
|
|
||||||
|
void ( *pfnGetPlayerInfo ) ( int ent_num, hud_player_info_t *pinfo );
|
||||||
|
|
||||||
|
// sound handlers
|
||||||
|
void ( *pfnPlaySoundByName ) ( char *szSound, float volume );
|
||||||
|
void ( *pfnPlaySoundByIndex ) ( int iSound, float volume );
|
||||||
|
|
||||||
|
// vector helpers
|
||||||
|
void ( *pfnAngleVectors ) ( const float * vecAngles, float * forward, float * right, float * up );
|
||||||
|
|
||||||
|
// text message system
|
||||||
|
client_textmessage_t *( *pfnTextMessageGet ) ( const char *pName );
|
||||||
|
int ( *pfnDrawCharacter ) ( int x, int y, int number, int r, int g, int b );
|
||||||
|
int ( *pfnDrawConsoleString ) ( int x, int y, char *string );
|
||||||
|
void ( *pfnDrawSetTextColor ) ( float r, float g, float b );
|
||||||
|
void ( *pfnDrawConsoleStringLen )( const char *string, int *length, int *height );
|
||||||
|
|
||||||
|
void ( *pfnConsolePrint ) ( const char *string );
|
||||||
|
void ( *pfnCenterPrint ) ( const char *string );
|
||||||
|
|
||||||
|
|
||||||
|
// Added for user input processing
|
||||||
|
int ( *GetWindowCenterX ) ( void );
|
||||||
|
int ( *GetWindowCenterY ) ( void );
|
||||||
|
void ( *GetViewAngles ) ( float * );
|
||||||
|
void ( *SetViewAngles ) ( float * );
|
||||||
|
int ( *GetMaxClients ) ( void );
|
||||||
|
void ( *Cvar_SetValue ) ( char *cvar, float value );
|
||||||
|
|
||||||
|
int (*Cmd_Argc) (void);
|
||||||
|
char *( *Cmd_Argv ) ( int arg );
|
||||||
|
void ( *Con_Printf ) ( char *fmt, ... );
|
||||||
|
void ( *Con_DPrintf ) ( char *fmt, ... );
|
||||||
|
void ( *Con_NPrintf ) ( int pos, char *fmt, ... );
|
||||||
|
void ( *Con_NXPrintf ) ( struct con_nprint_s *info, char *fmt, ... );
|
||||||
|
|
||||||
|
const char *( *PhysInfo_ValueForKey ) ( const char *key );
|
||||||
|
const char *( *ServerInfo_ValueForKey )( const char *key );
|
||||||
|
float ( *GetClientMaxspeed ) ( void );
|
||||||
|
int ( *CheckParm ) ( char *parm, char **ppnext );
|
||||||
|
void ( *Key_Event ) ( int key, int down );
|
||||||
|
void ( *GetMousePosition ) ( int *mx, int *my );
|
||||||
|
int ( *IsNoClipping ) ( void );
|
||||||
|
|
||||||
|
struct cl_entity_s *( *GetLocalPlayer ) ( void );
|
||||||
|
struct cl_entity_s *( *GetViewModel ) ( void );
|
||||||
|
struct cl_entity_s *( *GetEntityByIndex ) ( int idx );
|
||||||
|
|
||||||
|
float ( *GetClientTime ) ( void );
|
||||||
|
void ( *V_CalcShake ) ( void );
|
||||||
|
void ( *V_ApplyShake ) ( float *origin, float *angles, float factor );
|
||||||
|
|
||||||
|
int ( *PM_PointContents ) ( float *point, int *truecontents );
|
||||||
|
int ( *PM_WaterEntity ) ( float *p );
|
||||||
|
struct pmtrace_s *( *PM_TraceLine ) ( float *start, float *end, int flags, int usehull, int ignore_pe );
|
||||||
|
|
||||||
|
struct model_s *( *CL_LoadModel ) ( const char *modelname, int *index );
|
||||||
|
int ( *CL_CreateVisibleEntity ) ( int type, struct cl_entity_s *ent );
|
||||||
|
|
||||||
|
const struct model_s * ( *GetSpritePointer ) ( HSPRITE hSprite );
|
||||||
|
void ( *pfnPlaySoundByNameAtLocation ) ( char *szSound, float volume, float *origin );
|
||||||
|
|
||||||
|
unsigned short ( *pfnPrecacheEvent ) ( int type, const char* psz );
|
||||||
|
void ( *pfnPlaybackEvent ) ( int flags, const struct edict_s *pInvoker, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
|
||||||
|
void ( *pfnWeaponAnim ) ( int iAnim, int body );
|
||||||
|
float ( *pfnRandomFloat ) ( float flLow, float flHigh );
|
||||||
|
long ( *pfnRandomLong ) ( long lLow, long lHigh );
|
||||||
|
void ( *pfnHookEvent ) ( char *name, void ( *pfnEvent )( struct event_args_s *args ) );
|
||||||
|
int (*Con_IsVisible) ();
|
||||||
|
const char *( *pfnGetGameDirectory ) ( void );
|
||||||
|
struct cvar_s *( *pfnGetCvarPointer ) ( const char *szName );
|
||||||
|
const char *( *Key_LookupBinding ) ( const char *pBinding );
|
||||||
|
const char *( *pfnGetLevelName ) ( void );
|
||||||
|
void ( *pfnGetScreenFade ) ( struct screenfade_s *fade );
|
||||||
|
void ( *pfnSetScreenFade ) ( struct screenfade_s *fade );
|
||||||
|
void *( *VGui_GetPanel ) ( );
|
||||||
|
void ( *VGui_ViewportPaintBackground ) (int extents[4]);
|
||||||
|
|
||||||
|
byte* (*COM_LoadFile) ( char *path, int usehunk, int *pLength );
|
||||||
|
char* (*COM_ParseFile) ( char *data, char *token );
|
||||||
|
void (*COM_FreeFile) ( void *buffer );
|
||||||
|
|
||||||
|
struct triangleapi_s *pTriAPI;
|
||||||
|
struct efx_api_s *pEfxAPI;
|
||||||
|
struct event_api_s *pEventAPI;
|
||||||
|
struct demo_api_s *pDemoAPI;
|
||||||
|
struct net_api_s *pNetAPI;
|
||||||
|
struct IVoiceTweak_s *pVoiceTweak;
|
||||||
|
|
||||||
|
// returns 1 if the client is a spectator only (connected to a proxy), 0 otherwise or 2 if in dev_overview mode
|
||||||
|
int ( *IsSpectateOnly ) ( void );
|
||||||
|
struct model_s *( *LoadMapSprite ) ( const char *filename );
|
||||||
|
|
||||||
|
// file search functions
|
||||||
|
void ( *COM_AddAppDirectoryToSearchPath ) ( const char *pszBaseDir, const char *appName );
|
||||||
|
int ( *COM_ExpandFilename) ( const char *fileName, char *nameOutBuffer, int nameOutBufferSize );
|
||||||
|
|
||||||
|
// User info
|
||||||
|
// playerNum is in the range (1, MaxClients)
|
||||||
|
// returns NULL if player doesn't exit
|
||||||
|
// returns "" if no value is set
|
||||||
|
const char *( *PlayerInfo_ValueForKey )( int playerNum, const char *key );
|
||||||
|
void ( *PlayerInfo_SetValueForKey )( const char *key, const char *value );
|
||||||
|
|
||||||
|
// Gets a unique ID for the specified player. This is the same even if you see the player on a different server.
|
||||||
|
// iPlayer is an entity index, so client 0 would use iPlayer=1.
|
||||||
|
// Returns false if there is no player on the server in the specified slot.
|
||||||
|
qboolean (*GetPlayerUniqueID)(int iPlayer, char playerID[16]);
|
||||||
|
|
||||||
|
// TrackerID access
|
||||||
|
int (*GetTrackerIDForPlayer)(int playerSlot);
|
||||||
|
int (*GetPlayerForTrackerID)(int trackerID);
|
||||||
|
|
||||||
|
// Same as pfnServerCmd, but the message goes in the unreliable stream so it can't clog the net stream
|
||||||
|
// (but it might not get there).
|
||||||
|
int ( *pfnServerCmdUnreliable )( char *szCmdString );
|
||||||
|
|
||||||
|
void ( *pfnGetMousePos )( struct tagPOINT *ppt );
|
||||||
|
void ( *pfnSetMousePos )( int x, int y );
|
||||||
|
void ( *pfnSetMouseEnable )( qboolean fEnable );
|
||||||
|
} cl_enginefunc_t;
|
||||||
|
|
||||||
|
#ifndef IN_BUTTONS_H
|
||||||
|
#include "in_buttons.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CLDLL_INTERFACE_VERSION 7
|
||||||
|
|
||||||
|
extern void ClientDLL_Init( void ); // from cdll_int.c
|
||||||
|
extern void ClientDLL_Shutdown( void );
|
||||||
|
extern void ClientDLL_HudInit( void );
|
||||||
|
extern void ClientDLL_HudVidInit( void );
|
||||||
|
extern void ClientDLL_UpdateClientData( void );
|
||||||
|
extern void ClientDLL_Frame( double time );
|
||||||
|
extern void ClientDLL_HudRedraw( int intermission );
|
||||||
|
extern void ClientDLL_MoveClient( struct playermove_s *ppmove );
|
||||||
|
extern void ClientDLL_ClientMoveInit( struct playermove_s *ppmove );
|
||||||
|
extern char ClientDLL_ClientTextureType( char *name );
|
||||||
|
|
||||||
|
extern void ClientDLL_CreateMove( float frametime, struct usercmd_s *cmd, int active );
|
||||||
|
extern void ClientDLL_ActivateMouse( void );
|
||||||
|
extern void ClientDLL_DeactivateMouse( void );
|
||||||
|
extern void ClientDLL_MouseEvent( int mstate );
|
||||||
|
extern void ClientDLL_ClearStates( void );
|
||||||
|
extern int ClientDLL_IsThirdPerson( void );
|
||||||
|
extern void ClientDLL_GetCameraOffsets( float *ofs );
|
||||||
|
extern int ClientDLL_GraphKeyDown( void );
|
||||||
|
extern struct kbutton_s *ClientDLL_FindKey( const char *name );
|
||||||
|
extern void ClientDLL_CAM_Think( void );
|
||||||
|
extern void ClientDLL_IN_Accumulate( void );
|
||||||
|
extern void ClientDLL_CalcRefdef( struct ref_params_s *pparams );
|
||||||
|
extern int ClientDLL_AddEntity( int type, struct cl_entity_s *ent );
|
||||||
|
extern void ClientDLL_CreateEntities( void );
|
||||||
|
|
||||||
|
extern void ClientDLL_DrawNormalTriangles( void );
|
||||||
|
extern void ClientDLL_DrawTransparentTriangles( void );
|
||||||
|
extern void ClientDLL_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity );
|
||||||
|
extern void ClientDLL_PostRunCmd( struct local_state_s *from, struct local_state_s *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int random_seed );
|
||||||
|
extern void ClientDLL_TxferLocalOverrides( struct entity_state_s *state, const struct clientdata_s *client );
|
||||||
|
extern void ClientDLL_ProcessPlayerState( struct entity_state_s *dst, const struct entity_state_s *src );
|
||||||
|
extern void ClientDLL_TxferPredictionData ( struct entity_state_s *ps, const struct entity_state_s *pps, struct clientdata_s *pcd, const struct clientdata_s *ppcd, struct weapon_data_s *wd, const struct weapon_data_s *pwd );
|
||||||
|
extern void ClientDLL_ReadDemoBuffer( int size, unsigned char *buffer );
|
||||||
|
extern int ClientDLL_ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size );
|
||||||
|
extern int ClientDLL_GetHullBounds( int hullnumber, float *mins, float *maxs );
|
||||||
|
|
||||||
|
extern void ClientDLL_VGui_ConsolePrint(const char* text);
|
||||||
|
|
||||||
|
extern int ClientDLL_Key_Event( int down, int keynum, const char *pszCurrentBinding );
|
||||||
|
extern void ClientDLL_TempEntUpdate( double ft, double ct, double grav, struct tempent_s **ppFreeTE, struct tempent_s **ppActiveTE, int ( *addTEntity )( struct cl_entity_s *pEntity ), void ( *playTESound )( struct tempent_s *pTemp, float damp ) );
|
||||||
|
extern struct cl_entity_s *ClientDLL_GetUserEntity( int index );
|
||||||
|
extern void ClientDLL_VoiceStatus(int entindex, qboolean bTalking);
|
||||||
|
extern void ClientDLL_DirectorMessage( int iSize, void *pbuf );
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // CDLL_INT_H
|
||||||
@@ -17,7 +17,9 @@
|
|||||||
#ifndef CUSTOM_H
|
#ifndef CUSTOM_H
|
||||||
#define CUSTOM_H
|
#define CUSTOM_H
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#ifndef __MINGW32__
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#endif /* not __MINGW32__ */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/***
|
/***
|
||||||
*
|
*
|
||||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||||
*
|
*
|
||||||
* This product contains software technology licensed from Id
|
* This product contains software technology licensed from Id
|
||||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#if !defined EDICT_H
|
#if !defined EDICT_H
|
||||||
#define EDICT_H
|
#define EDICT_H
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#ifndef __MINGW32__
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#endif /* not __MINGW32__ */
|
||||||
#endif
|
#endif
|
||||||
#define MAX_ENT_LEAFS 48
|
#define MAX_ENT_LEAFS 48
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/***
|
/***
|
||||||
*
|
*
|
||||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
* Copyright (c) 1999, Valve LLC. All rights reserved.
|
||||||
*
|
*
|
||||||
* This product contains software technology licensed from Id
|
* This product contains software technology licensed from Id
|
||||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
#ifndef EIFACE_H
|
#ifndef EIFACE_H
|
||||||
#define EIFACE_H
|
#define EIFACE_H
|
||||||
|
|
||||||
|
#include "archtypes.h" // DAL
|
||||||
|
|
||||||
#ifdef HLDEMO_BUILD
|
#ifdef HLDEMO_BUILD
|
||||||
#define INTERFACE_VERSION 001
|
#define INTERFACE_VERSION 001
|
||||||
#else // !HLDEMO_BUILD, i.e., regular version of HL
|
#else // !HLDEMO_BUILD, i.e., regular version of HL
|
||||||
@@ -24,6 +26,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "custom.h"
|
#include "custom.h"
|
||||||
#include "cvardef.h"
|
#include "cvardef.h"
|
||||||
|
#include "Sequence.h"
|
||||||
//
|
//
|
||||||
// Defines entity interface between engine and DLLs.
|
// Defines entity interface between engine and DLLs.
|
||||||
// This header file included by engine files and DLL files.
|
// This header file included by engine files and DLL files.
|
||||||
@@ -63,6 +66,7 @@ typedef enum
|
|||||||
force_exactfile, // File on client must exactly match server's file
|
force_exactfile, // File on client must exactly match server's file
|
||||||
force_model_samebounds, // For model files only, the geometry must fit in the same bbox
|
force_model_samebounds, // For model files only, the geometry must fit in the same bbox
|
||||||
force_model_specifybounds, // For model files only, the geometry must fit in the specified bbox
|
force_model_specifybounds, // For model files only, the geometry must fit in the specified bbox
|
||||||
|
force_model_specifybounds_if_avail, // For Steam model files only, the geometry must fit in the specified bbox (if the file is available)
|
||||||
} FORCE_TYPE;
|
} FORCE_TYPE;
|
||||||
|
|
||||||
// Returned by TraceLine
|
// Returned by TraceLine
|
||||||
@@ -96,6 +100,7 @@ typedef struct
|
|||||||
|
|
||||||
#include "../common/crc.h"
|
#include "../common/crc.h"
|
||||||
|
|
||||||
|
|
||||||
// Engine hands this to DLLs for functionality callbacks
|
// Engine hands this to DLLs for functionality callbacks
|
||||||
typedef struct enginefuncs_s
|
typedef struct enginefuncs_s
|
||||||
{
|
{
|
||||||
@@ -161,8 +166,13 @@ typedef struct enginefuncs_s
|
|||||||
void (*pfnCVarSetFloat) (const char *szVarName, float flValue);
|
void (*pfnCVarSetFloat) (const char *szVarName, float flValue);
|
||||||
void (*pfnCVarSetString) (const char *szVarName, const char *szValue);
|
void (*pfnCVarSetString) (const char *szVarName, const char *szValue);
|
||||||
void (*pfnAlertMessage) (ALERT_TYPE atype, char *szFmt, ...);
|
void (*pfnAlertMessage) (ALERT_TYPE atype, char *szFmt, ...);
|
||||||
|
#ifdef HLSDK_3_2_OLD_EIFACE
|
||||||
void (*pfnEngineFprintf) (FILE *pfile, char *szFmt, ...);
|
void (*pfnEngineFprintf) (FILE *pfile, char *szFmt, ...);
|
||||||
void* (*pfnPvAllocEntPrivateData) (edict_t *pEdict, long cb);
|
void* (*pfnPvAllocEntPrivateData) (edict_t *pEdict, long cb);
|
||||||
|
#else
|
||||||
|
void (*pfnEngineFprintf) (void *pfile, char *szFmt, ...);
|
||||||
|
void* (*pfnPvAllocEntPrivateData) (edict_t *pEdict, int32 cb);
|
||||||
|
#endif
|
||||||
void* (*pfnPvEntPrivateData) (edict_t *pEdict);
|
void* (*pfnPvEntPrivateData) (edict_t *pEdict);
|
||||||
void (*pfnFreeEntPrivateData) (edict_t *pEdict);
|
void (*pfnFreeEntPrivateData) (edict_t *pEdict);
|
||||||
const char* (*pfnSzFromIndex) (int iString);
|
const char* (*pfnSzFromIndex) (int iString);
|
||||||
@@ -177,8 +187,13 @@ typedef struct enginefuncs_s
|
|||||||
int (*pfnRegUserMsg) (const char *pszName, int iSize);
|
int (*pfnRegUserMsg) (const char *pszName, int iSize);
|
||||||
void (*pfnAnimationAutomove) (const edict_t* pEdict, float flTime);
|
void (*pfnAnimationAutomove) (const edict_t* pEdict, float flTime);
|
||||||
void (*pfnGetBonePosition) (const edict_t* pEdict, int iBone, float *rgflOrigin, float *rgflAngles );
|
void (*pfnGetBonePosition) (const edict_t* pEdict, int iBone, float *rgflOrigin, float *rgflAngles );
|
||||||
|
#ifdef HLSDK_3_2_OLD_EIFACE
|
||||||
unsigned long (*pfnFunctionFromName) ( const char *pName );
|
unsigned long (*pfnFunctionFromName) ( const char *pName );
|
||||||
const char *(*pfnNameForFunction) ( unsigned long function );
|
const char *(*pfnNameForFunction) ( unsigned long function );
|
||||||
|
#else
|
||||||
|
uint32 (*pfnFunctionFromName) ( const char *pName );
|
||||||
|
const char *(*pfnNameForFunction) ( uint32 function );
|
||||||
|
#endif
|
||||||
void (*pfnClientPrintf) ( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg ); // JOHN: engine callbacks so game DLL can print messages to individual clients
|
void (*pfnClientPrintf) ( edict_t* pEdict, PRINT_TYPE ptype, const char *szMsg ); // JOHN: engine callbacks so game DLL can print messages to individual clients
|
||||||
void (*pfnServerPrint) ( const char *szMsg );
|
void (*pfnServerPrint) ( const char *szMsg );
|
||||||
const char *(*pfnCmd_Args) ( void ); // these 3 added
|
const char *(*pfnCmd_Args) ( void ); // these 3 added
|
||||||
@@ -189,7 +204,11 @@ typedef struct enginefuncs_s
|
|||||||
void (*pfnCRC32_ProcessBuffer) (CRC32_t *pulCRC, void *p, int len);
|
void (*pfnCRC32_ProcessBuffer) (CRC32_t *pulCRC, void *p, int len);
|
||||||
void (*pfnCRC32_ProcessByte) (CRC32_t *pulCRC, unsigned char ch);
|
void (*pfnCRC32_ProcessByte) (CRC32_t *pulCRC, unsigned char ch);
|
||||||
CRC32_t (*pfnCRC32_Final) (CRC32_t pulCRC);
|
CRC32_t (*pfnCRC32_Final) (CRC32_t pulCRC);
|
||||||
|
#ifdef HLSDK_3_2_OLD_EIFACE
|
||||||
long (*pfnRandomLong) (long lLow, long lHigh);
|
long (*pfnRandomLong) (long lLow, long lHigh);
|
||||||
|
#else
|
||||||
|
int32 (*pfnRandomLong) (int32 lLow, int32 lHigh);
|
||||||
|
#endif
|
||||||
float (*pfnRandomFloat) (float flLow, float flHigh);
|
float (*pfnRandomFloat) (float flLow, float flHigh);
|
||||||
void (*pfnSetView) (const edict_t *pClient, const edict_t *pViewent );
|
void (*pfnSetView) (const edict_t *pClient, const edict_t *pViewent );
|
||||||
float (*pfnTime) ( void );
|
float (*pfnTime) ( void );
|
||||||
@@ -261,7 +280,47 @@ typedef struct enginefuncs_s
|
|||||||
|
|
||||||
const char *(*pfnGetPlayerAuthId) ( edict_t *e );
|
const char *(*pfnGetPlayerAuthId) ( edict_t *e );
|
||||||
|
|
||||||
|
// PSV: Added for CZ training map
|
||||||
|
// const char *(*pfnKeyNameForBinding) ( const char* pBinding );
|
||||||
|
|
||||||
|
sequenceEntry_s* (*pfnSequenceGet) ( const char* fileName, const char* entryName );
|
||||||
|
sentenceEntry_s* (*pfnSequencePickSentence) ( const char* groupName, int pickMethod, int *picked );
|
||||||
|
|
||||||
|
// LH: Give access to filesize via filesystem
|
||||||
|
int (*pfnGetFileSize) ( char *filename );
|
||||||
|
|
||||||
|
unsigned int (*pfnGetApproxWavePlayLen) (const char *filepath);
|
||||||
|
// MDC: Added for CZ career-mode
|
||||||
|
int (*pfnIsCareerMatch) ( void );
|
||||||
|
|
||||||
|
// BGC: return the number of characters of the localized string referenced by using "label"
|
||||||
|
int (*pfnGetLocalizedStringLength) (const char *label);
|
||||||
|
|
||||||
|
// BGC: added to facilitate persistent storage of tutor message decay values for
|
||||||
|
// different career game profiles. Also needs to persist regardless of mp.dll being
|
||||||
|
// destroyed and recreated.
|
||||||
|
void (*pfnRegisterTutorMessageShown) (int mid);
|
||||||
|
int (*pfnGetTimesTutorMessageShown) (int mid);
|
||||||
|
void (*pfnProcessTutorMessageDecayBuffer) (int *buffer, int bufferLength);
|
||||||
|
void (*pfnConstructTutorMessageDecayBuffer) (int *buffer, int bufferLength);
|
||||||
|
void (*pfnResetTutorMessageDecayData) ( void );
|
||||||
|
|
||||||
|
// Added 2005/08/11 (no SDK update):
|
||||||
|
void (*pfnQueryClientCvarValue) (const edict_t *player, const char *cvarName);
|
||||||
|
|
||||||
|
// Added 2005/11/21 (no SDK update):
|
||||||
|
void (*pfnQueryClientCvarValue2) (const edict_t *player, const char *cvarName, int requestID);
|
||||||
|
|
||||||
|
// Added 2009/06/19 (no SDK update):
|
||||||
|
int (*pfnEngCheckParm) (const char *pchCmdLineToken, char **pchNextVal);
|
||||||
|
|
||||||
|
#ifdef __METAMOD_BUILD__
|
||||||
|
//extra (future updates)
|
||||||
|
void * extra_functions[16];
|
||||||
|
#endif /*__METAMOD_BUILD__*/
|
||||||
} enginefuncs_t;
|
} enginefuncs_t;
|
||||||
|
|
||||||
|
|
||||||
// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 138
|
// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 138
|
||||||
|
|
||||||
// Passed to pfnKeyValue
|
// Passed to pfnKeyValue
|
||||||
@@ -270,7 +329,11 @@ typedef struct KeyValueData_s
|
|||||||
char *szClassName; // in: entity classname
|
char *szClassName; // in: entity classname
|
||||||
char *szKeyName; // in: name of key
|
char *szKeyName; // in: name of key
|
||||||
char *szValue; // in: value of key
|
char *szValue; // in: value of key
|
||||||
|
#ifdef HLSDK_3_2_OLD_EIFACE
|
||||||
long fHandled; // out: DLL sets to true if key-value pair was understood
|
long fHandled; // out: DLL sets to true if key-value pair was understood
|
||||||
|
#else
|
||||||
|
int32 fHandled; // out: DLL sets to true if key-value pair was understood
|
||||||
|
#endif
|
||||||
} KeyValueData;
|
} KeyValueData;
|
||||||
|
|
||||||
|
|
||||||
@@ -357,9 +420,11 @@ typedef enum _fieldtypes
|
|||||||
FIELD_TYPECOUNT, // MUST BE LAST
|
FIELD_TYPECOUNT, // MUST BE LAST
|
||||||
} FIELDTYPE;
|
} FIELDTYPE;
|
||||||
|
|
||||||
|
#ifndef linux
|
||||||
#ifndef offsetof
|
#ifndef offsetof
|
||||||
#define offsetof(s,m) (size_t)&(((s *)0)->m)
|
#define offsetof(s,m) (size_t)&(((s *)0)->m)
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#define _FIELD(type,name,fieldtype,count,flags) { fieldtype, #name, offsetof(type, name), count, flags }
|
#define _FIELD(type,name,fieldtype,count,flags) { fieldtype, #name, offsetof(type, name), count, flags }
|
||||||
#define DEFINE_FIELD(type,name,fieldtype) _FIELD(type, name, fieldtype, 1, 0)
|
#define DEFINE_FIELD(type,name,fieldtype) _FIELD(type, name, fieldtype, 1, 0)
|
||||||
@@ -380,7 +445,16 @@ typedef struct
|
|||||||
short flags;
|
short flags;
|
||||||
} TYPEDESCRIPTION;
|
} TYPEDESCRIPTION;
|
||||||
|
|
||||||
#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
|
// Fixed MSVC compiling, by Nikolay "The Storm" Baklicharov.
|
||||||
|
#if defined _MSC_VER && _MSC_VER >= 1400
|
||||||
|
#ifndef ARRAYSIZE
|
||||||
|
#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
|
||||||
|
#endif
|
||||||
|
#else /* MSVC 8.0 */
|
||||||
|
#ifndef ARRAYSIZE
|
||||||
|
#define ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -481,6 +555,14 @@ typedef struct
|
|||||||
void (*pfnOnFreeEntPrivateData)(edict_t *pEnt);
|
void (*pfnOnFreeEntPrivateData)(edict_t *pEnt);
|
||||||
void (*pfnGameShutdown)(void);
|
void (*pfnGameShutdown)(void);
|
||||||
int (*pfnShouldCollide)( edict_t *pentTouched, edict_t *pentOther );
|
int (*pfnShouldCollide)( edict_t *pentTouched, edict_t *pentOther );
|
||||||
|
|
||||||
|
// Added 2005/08/11 (no SDK update):
|
||||||
|
void (*pfnCvarValue)( const edict_t *pEnt, const char *value );
|
||||||
|
|
||||||
|
// Added 2005/11/21 (no SDK update):
|
||||||
|
// value is "Bad CVAR request" on failure (i.e that user is not connected or the cvar does not exist).
|
||||||
|
// value is "Bad Player" if invalid player edict.
|
||||||
|
void (*pfnCvarValue2)( const edict_t *pEnt, int requestID, const char *cvarName, const char *value );
|
||||||
} NEW_DLL_FUNCTIONS;
|
} NEW_DLL_FUNCTIONS;
|
||||||
typedef int (*NEW_DLL_FUNCTIONS_FN)( NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
|
typedef int (*NEW_DLL_FUNCTIONS_FN)( NEW_DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
|
||||||
|
|
||||||
@@ -490,4 +572,4 @@ extern NEW_DLL_FUNCTIONS gNewDLLFunctions;
|
|||||||
typedef int (*APIFUNCTION)( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion );
|
typedef int (*APIFUNCTION)( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion );
|
||||||
typedef int (*APIFUNCTION2)( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
|
typedef int (*APIFUNCTION2)( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
|
||||||
|
|
||||||
#endif EIFACE_H
|
#endif /* EIFACE_H */
|
||||||
|
|||||||
131
src/engine/keydefs.h
Normal file
131
src/engine/keydefs.h
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
|
||||||
|
//
|
||||||
|
// Purpose:
|
||||||
|
//
|
||||||
|
// $NoKeywords: $
|
||||||
|
//=============================================================================
|
||||||
|
|
||||||
|
// keydefs.h
|
||||||
|
#ifndef KEYDEFS_H
|
||||||
|
#define KEYDEFS_H
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifndef __MINGW32__
|
||||||
|
#pragma once
|
||||||
|
#endif /* not __MINGW32__ */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
// these are the key numbers that should be passed to Key_Event
|
||||||
|
//
|
||||||
|
#define K_TAB 9
|
||||||
|
#define K_ENTER 13
|
||||||
|
#define K_ESCAPE 27
|
||||||
|
#define K_SPACE 32
|
||||||
|
|
||||||
|
// normal keys should be passed as lowercased ascii
|
||||||
|
|
||||||
|
#define K_BACKSPACE 127
|
||||||
|
#define K_UPARROW 128
|
||||||
|
#define K_DOWNARROW 129
|
||||||
|
#define K_LEFTARROW 130
|
||||||
|
#define K_RIGHTARROW 131
|
||||||
|
|
||||||
|
#define K_ALT 132
|
||||||
|
#define K_CTRL 133
|
||||||
|
#define K_SHIFT 134
|
||||||
|
#define K_F1 135
|
||||||
|
#define K_F2 136
|
||||||
|
#define K_F3 137
|
||||||
|
#define K_F4 138
|
||||||
|
#define K_F5 139
|
||||||
|
#define K_F6 140
|
||||||
|
#define K_F7 141
|
||||||
|
#define K_F8 142
|
||||||
|
#define K_F9 143
|
||||||
|
#define K_F10 144
|
||||||
|
#define K_F11 145
|
||||||
|
#define K_F12 146
|
||||||
|
#define K_INS 147
|
||||||
|
#define K_DEL 148
|
||||||
|
#define K_PGDN 149
|
||||||
|
#define K_PGUP 150
|
||||||
|
#define K_HOME 151
|
||||||
|
#define K_END 152
|
||||||
|
|
||||||
|
#define K_KP_HOME 160
|
||||||
|
#define K_KP_UPARROW 161
|
||||||
|
#define K_KP_PGUP 162
|
||||||
|
#define K_KP_LEFTARROW 163
|
||||||
|
#define K_KP_5 164
|
||||||
|
#define K_KP_RIGHTARROW 165
|
||||||
|
#define K_KP_END 166
|
||||||
|
#define K_KP_DOWNARROW 167
|
||||||
|
#define K_KP_PGDN 168
|
||||||
|
#define K_KP_ENTER 169
|
||||||
|
#define K_KP_INS 170
|
||||||
|
#define K_KP_DEL 171
|
||||||
|
#define K_KP_SLASH 172
|
||||||
|
#define K_KP_MINUS 173
|
||||||
|
#define K_KP_PLUS 174
|
||||||
|
#define K_CAPSLOCK 175
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// joystick buttons
|
||||||
|
//
|
||||||
|
#define K_JOY1 203
|
||||||
|
#define K_JOY2 204
|
||||||
|
#define K_JOY3 205
|
||||||
|
#define K_JOY4 206
|
||||||
|
|
||||||
|
//
|
||||||
|
// aux keys are for multi-buttoned joysticks to generate so they can use
|
||||||
|
// the normal binding process
|
||||||
|
//
|
||||||
|
#define K_AUX1 207
|
||||||
|
#define K_AUX2 208
|
||||||
|
#define K_AUX3 209
|
||||||
|
#define K_AUX4 210
|
||||||
|
#define K_AUX5 211
|
||||||
|
#define K_AUX6 212
|
||||||
|
#define K_AUX7 213
|
||||||
|
#define K_AUX8 214
|
||||||
|
#define K_AUX9 215
|
||||||
|
#define K_AUX10 216
|
||||||
|
#define K_AUX11 217
|
||||||
|
#define K_AUX12 218
|
||||||
|
#define K_AUX13 219
|
||||||
|
#define K_AUX14 220
|
||||||
|
#define K_AUX15 221
|
||||||
|
#define K_AUX16 222
|
||||||
|
#define K_AUX17 223
|
||||||
|
#define K_AUX18 224
|
||||||
|
#define K_AUX19 225
|
||||||
|
#define K_AUX20 226
|
||||||
|
#define K_AUX21 227
|
||||||
|
#define K_AUX22 228
|
||||||
|
#define K_AUX23 229
|
||||||
|
#define K_AUX24 230
|
||||||
|
#define K_AUX25 231
|
||||||
|
#define K_AUX26 232
|
||||||
|
#define K_AUX27 233
|
||||||
|
#define K_AUX28 234
|
||||||
|
#define K_AUX29 235
|
||||||
|
#define K_AUX30 236
|
||||||
|
#define K_AUX31 237
|
||||||
|
#define K_AUX32 238
|
||||||
|
#define K_MWHEELDOWN 239
|
||||||
|
#define K_MWHEELUP 240
|
||||||
|
|
||||||
|
#define K_PAUSE 255
|
||||||
|
|
||||||
|
//
|
||||||
|
// mouse buttons generate virtual keys
|
||||||
|
//
|
||||||
|
#define K_MOUSE1 241
|
||||||
|
#define K_MOUSE2 242
|
||||||
|
#define K_MOUSE3 243
|
||||||
|
#define K_MOUSE4 244
|
||||||
|
#define K_MOUSE5 245
|
||||||
|
|
||||||
|
#endif // KEYDEFS_H
|
||||||
@@ -15,7 +15,9 @@
|
|||||||
#ifndef PROGDEFS_H
|
#ifndef PROGDEFS_H
|
||||||
#define PROGDEFS_H
|
#define PROGDEFS_H
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#ifndef __MINGW32__
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#endif /* not __MINGW32__ */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|||||||
82
src/engine/progs.h
Normal file
82
src/engine/progs.h
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
/***
|
||||||
|
*
|
||||||
|
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||||
|
*
|
||||||
|
* This product contains software technology licensed from Id
|
||||||
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||||
|
* All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use, distribution, and modification of this source code and/or resulting
|
||||||
|
* object code is restricted to non-commercial enhancements to products from
|
||||||
|
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||||
|
* without written permission from Valve LLC.
|
||||||
|
*
|
||||||
|
****/
|
||||||
|
#ifndef PROGS_H
|
||||||
|
#define PROGS_H
|
||||||
|
|
||||||
|
#include "progdefs.h"
|
||||||
|
|
||||||
|
// 16 simultaneous events, max
|
||||||
|
#define MAX_EVENT_QUEUE 64
|
||||||
|
|
||||||
|
#define DEFAULT_EVENT_RESENDS 1
|
||||||
|
|
||||||
|
#include "event_flags.h"
|
||||||
|
|
||||||
|
typedef struct event_info_s event_info_t;
|
||||||
|
|
||||||
|
#include "event_args.h"
|
||||||
|
|
||||||
|
struct event_info_s
|
||||||
|
{
|
||||||
|
unsigned short index; // 0 implies not in use
|
||||||
|
|
||||||
|
short packet_index; // Use data from state info for entity in delta_packet . -1 implies separate info based on event
|
||||||
|
// parameter signature
|
||||||
|
short entity_index; // The edict this event is associated with
|
||||||
|
|
||||||
|
float fire_time; // if non-zero, the time when the event should be fired ( fixed up on the client )
|
||||||
|
|
||||||
|
event_args_t args;
|
||||||
|
|
||||||
|
// CLIENT ONLY
|
||||||
|
int flags; // Reliable or not, etc.
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct event_state_s event_state_t;
|
||||||
|
|
||||||
|
struct event_state_s
|
||||||
|
{
|
||||||
|
struct event_info_s ei[ MAX_EVENT_QUEUE ];
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined( ENTITY_STATEH )
|
||||||
|
#include "entity_state.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined( EDICT_H )
|
||||||
|
#include "edict.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m)))
|
||||||
|
#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area)
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
extern char *pr_strings;
|
||||||
|
extern globalvars_t gGlobalVariables;
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
edict_t *ED_Alloc (void);
|
||||||
|
void ED_Free (edict_t *ed);
|
||||||
|
void ED_LoadFromFile (char *data);
|
||||||
|
|
||||||
|
edict_t *EDICT_NUM(int n);
|
||||||
|
int NUM_FOR_EDICT(const edict_t *e);
|
||||||
|
|
||||||
|
#define PROG_TO_EDICT(e) ((edict_t *)((byte *)sv.edicts + e))
|
||||||
|
|
||||||
|
#endif // PROGS_H
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/***
|
/***
|
||||||
*
|
*
|
||||||
* Copyright (c) 1999, Valve LLC. All rights reserved.
|
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||||
*
|
*
|
||||||
* This product contains software technology licensed from Id
|
* This product contains software technology licensed from Id
|
||||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||||
|
|||||||
3
src/metamod/.gitignore
vendored
3
src/metamod/.gitignore
vendored
@@ -1,3 +0,0 @@
|
|||||||
msgs/
|
|
||||||
opt.*/
|
|
||||||
debug.*/
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
MODNAME = metamod
|
|
||||||
|
|
||||||
#__METAMOD_BUILD__ for our special eiface.h
|
|
||||||
EXTRA_CFLAGS += -D__METAMOD_BUILD__
|
|
||||||
#-DMETA_PERFMON
|
|
||||||
|
|
||||||
SRCFILES = api_hook.cpp api_info.cpp commands_meta.cpp conf_meta.cpp \
|
|
||||||
dllapi.cpp engine_api.cpp engineinfo.cpp game_support.cpp \
|
|
||||||
game_autodetect.cpp h_export.cpp linkgame.cpp linkplug.cpp \
|
|
||||||
log_meta.cpp meta_eiface.cpp metamod.cpp mlist.cpp mplayer.cpp \
|
|
||||||
mplugin.cpp mqueue.cpp mreg.cpp mutil.cpp osdep.cpp \
|
|
||||||
osdep_p.cpp reg_support.cpp sdk_util.cpp studioapi.cpp \
|
|
||||||
support_meta.cpp thread_logparse.cpp vdate.cpp
|
|
||||||
|
|
||||||
INFOFILES = info_name.h vers_meta.h
|
|
||||||
RESFILE = res_meta.rc
|
|
||||||
|
|
||||||
ifeq "$(OS)" "linux"
|
|
||||||
SRCFILES+=osdep_linkent_linux.cpp osdep_detect_gamedll_linux.cpp
|
|
||||||
EXTRA_LINK+=
|
|
||||||
else
|
|
||||||
SRCFILES+=osdep_linkent_win32.cpp osdep_detect_gamedll_win32.cpp
|
|
||||||
EXTRA_LINK+=-Xlinker --script -Xlinker i386pe.merge
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq "$(OPT)" "opt"
|
|
||||||
EXTRA_CFLAGS += -D__INTERNALS_USE_REGPARAMS__
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq "$(OPT)" "opt-fast"
|
|
||||||
EXTRA_CFLAGS += -D__INTERNALS_USE_REGPARAMS__
|
|
||||||
endif
|
|
||||||
|
|
||||||
#STLFILES = mreg.cpp
|
|
||||||
@@ -1,460 +0,0 @@
|
|||||||
# vi: set ts=4 sw=4 :
|
|
||||||
# vim: set tw=75 :
|
|
||||||
|
|
||||||
# MetaMod makefile
|
|
||||||
# Copyright (c) 2001-2003 Will Day <willday@hpgx.net>
|
|
||||||
#
|
|
||||||
# based on the Valve SDK 2.1 Makefile as well as the Makefile
|
|
||||||
# in adminmod by Alfred Reynolds.
|
|
||||||
#
|
|
||||||
# From SDK 2.1 dlls/Makefile:
|
|
||||||
#! Half-Life StandardSDK 2.0 mp_i386.so Makefile for i386 Linux
|
|
||||||
#! April 2000 by Leon Hartwig (jehannum@planethalflife.com)
|
|
||||||
|
|
||||||
|
|
||||||
# NOTE: This is a generic Makefile for metamod and the bundled plugins, and
|
|
||||||
# is symlinked into each subdir. Per-module config statements are in
|
|
||||||
# Config.mak in each subdir.
|
|
||||||
|
|
||||||
ifeq "$(shell uname | cut -d _ -f1)" "CYGWIN"
|
|
||||||
HOST=cygwin
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef COMSPEC
|
|
||||||
ifeq "$(HOST)" "cygwin"
|
|
||||||
ifeq "$(TARGET)" "win32"
|
|
||||||
OS=windows
|
|
||||||
else
|
|
||||||
OS=linux
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
OS=windows
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
OS=linux
|
|
||||||
endif
|
|
||||||
|
|
||||||
#############################################################################
|
|
||||||
# CONFIGURATION
|
|
||||||
#############################################################################
|
|
||||||
|
|
||||||
# TARGET amd64 disabled since Valve has dropped support for x86-64 server
|
|
||||||
#ifeq "$(TARGET)" "amd64"
|
|
||||||
# TARGETTYPE = amd64
|
|
||||||
#else
|
|
||||||
TARGETTYPE = i386
|
|
||||||
#endif
|
|
||||||
|
|
||||||
# set paths for your environment
|
|
||||||
ifeq "$(OS)" "linux"
|
|
||||||
INST_DIR=$(HOME)/half-life/cstrike/dlls
|
|
||||||
TEST_DIR=$(HOME)/test/tfc/dlls
|
|
||||||
TST_DIR=$(HOME)/tmp
|
|
||||||
else ## windows
|
|
||||||
INST_DIR=/hlserver/tfc/dlls
|
|
||||||
TEST_DIR=/hlserver/tfc/dlls
|
|
||||||
endif
|
|
||||||
|
|
||||||
DLLS_DIR=../dlls
|
|
||||||
SDKSRC=../hlsdk
|
|
||||||
METADIR=../metamod
|
|
||||||
|
|
||||||
COMPILE_TZ=EET
|
|
||||||
## Developer overrides
|
|
||||||
ifeq "$(USER)" "jussi"
|
|
||||||
COMPILE_TZ=EET
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
|
||||||
# OS DEPENDENCIES
|
|
||||||
#############################################################################
|
|
||||||
|
|
||||||
ifeq "$(OS)" "linux"
|
|
||||||
INSTALL=install -m 644
|
|
||||||
LD_WINDLL= i686-w64-mingw32-dllwrap
|
|
||||||
OSTARGET=linux
|
|
||||||
LIBFILE=$(LIBFILE_LINUX)
|
|
||||||
TARGET_FILE=$(TARGET_LINUX)
|
|
||||||
else ## windows
|
|
||||||
INSTALL=cp
|
|
||||||
LD_WINDLL= i686-w64-mingw32-dllwrap
|
|
||||||
OSTARGET=win32
|
|
||||||
LIBFILE=$(LIBFILE_WIN)
|
|
||||||
TARGET_FILE=$(TARGET_WIN)
|
|
||||||
endif
|
|
||||||
|
|
||||||
CC_WIN=i686-w64-mingw32-gcc
|
|
||||||
RES_WIN=i686-w64-mingw32-windres
|
|
||||||
|
|
||||||
ifeq "$(HOST)" "cygwin"
|
|
||||||
CC_WIN += -mno-cygwin
|
|
||||||
EXTRA_LINK += -L/lib/w32api
|
|
||||||
endif
|
|
||||||
|
|
||||||
OBJDIR_LINUX_OPT=opt.linux_$(TARGETTYPE)
|
|
||||||
OBJDIR_LINUX_DBG=debug.linux_$(TARGETTYPE)
|
|
||||||
OBJDIR_WIN_OPT=opt.win32
|
|
||||||
OBJDIR_WIN_DBG=debug.win32
|
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
|
||||||
# COMPILE OPTIONS - ARCHITECTURE AND OPTIMIZATIONS
|
|
||||||
#############################################################################
|
|
||||||
|
|
||||||
ifeq "$(OS)" "linux"
|
|
||||||
GCCMAJ = $(shell $(CC) -dumpversion | sed -e 's/\.[0-9][0-9]*//' -e 's/\.[0-9][0-9]*//')
|
|
||||||
GCCMIN = $(shell $(CC) -dumpversion | sed -e 's/[0-9]\.//;s/\.[0-9]//' -e 's/\.[0-9][0-9]*//')
|
|
||||||
else
|
|
||||||
GCCMAJ = $(shell $(CC_WIN) -dumpversion | sed -e 's/\.[0-9][0-9]*//' -e 's/\.[0-9][0-9]*//')
|
|
||||||
GCCMIN = $(shell $(CC_WIN) -dumpversion | sed -e 's/[0-9]\.//;s/\.[0-9]//' -e 's/\.[0-9][0-9]*//')
|
|
||||||
endif
|
|
||||||
|
|
||||||
GCCMAJ_GT_4 = $(shell if [ $(GCCMAJ) -gt 4 ]; then echo 1; else echo 0; fi)
|
|
||||||
|
|
||||||
ifeq "$(HOST)" "cygwin"
|
|
||||||
ifeq "$(TARGETTYPE)" "amd64"
|
|
||||||
CC=gcc-linux-x86_64
|
|
||||||
else
|
|
||||||
CC=gcc-linux
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
ifeq "$(TARGETTYPE)" "amd64"
|
|
||||||
CC=gcc -m64
|
|
||||||
else
|
|
||||||
CC=gcc -m32
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
MCPU=-mcpu
|
|
||||||
|
|
||||||
ifeq "$(GCCMAJ)" "3"
|
|
||||||
ifeq "$(GCCMIN)" "4"
|
|
||||||
MCPU=-mtune
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
ifeq "$(GCCMAJ)" "4"
|
|
||||||
MCPU=-mtune
|
|
||||||
endif
|
|
||||||
ifeq "$(GCCMAJ_GT_4)" "1"
|
|
||||||
MCPU=-mtune
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq "$(OS)" "linux"
|
|
||||||
CC_DEP=$(CC)
|
|
||||||
else
|
|
||||||
CC_DEP=$(CC_WIN)
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Note! About gcc optimization levels.
|
|
||||||
# There is four optimization levels:
|
|
||||||
# -O0 No optimizations.
|
|
||||||
# -O1 Optimize for smaller size.
|
|
||||||
# -O2 Optimize for speed without increasing size (alot).
|
|
||||||
# -O3 Optimize for speed, can result much greater filesize.
|
|
||||||
# Levels higher -O3 (-O6 for example) is threaded as -O3.
|
|
||||||
# See differences at "http://gcc.gnu.org/" (look for link to 'gcc manual').
|
|
||||||
|
|
||||||
# original safe optimization, from valve Makefile
|
|
||||||
#CCOPT = -O2 -ffast-math -funroll-loops \
|
|
||||||
# -fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
|
|
||||||
# -malign-jumps=2 -malign-functions=2
|
|
||||||
|
|
||||||
# safe optimization, adapted from adminmod Makefile
|
|
||||||
#CCOPT = -m486 -O6 -ffast-math -funroll-loops \
|
|
||||||
# -fexpensive-optimizations -malign-loops=2 -malign-jumps=2 \
|
|
||||||
# -malign-functions=2 -Wall
|
|
||||||
|
|
||||||
# full optimization, adapted from adminmod Makefile
|
|
||||||
# "WONT WORK WITH omit-frame-pointer"?
|
|
||||||
# - disable (unneeded) C++ exceptions and rtti code to save some space ?
|
|
||||||
|
|
||||||
CCOPT = $(CCO) $(CCOPT_ARCH) -fno-exceptions -fno-rtti
|
|
||||||
|
|
||||||
# optimization level; overridden for certain problematic files
|
|
||||||
CCO = -O2 -fomit-frame-pointer -funsafe-math-optimizations
|
|
||||||
CCO += -flto -fvisibility=hidden
|
|
||||||
|
|
||||||
# architecture tuning by target type
|
|
||||||
ifeq "$(TARGETTYPE)" "amd64"
|
|
||||||
CCOPT_ARCH =
|
|
||||||
else
|
|
||||||
CCOPT_ARCH = -march=i686 $(MCPU)=generic -msse -msse2
|
|
||||||
endif
|
|
||||||
|
|
||||||
# debugging; halt on warnings
|
|
||||||
CCDEBUG+= -ggdb3
|
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
|
||||||
# COMPILE SETUP
|
|
||||||
#############################################################################
|
|
||||||
|
|
||||||
SRCDIR=.
|
|
||||||
INCLUDEDIRS+=-I$(SRCDIR) -I$(METADIR) -I$(SDKSRC)/engine -I$(SDKSRC)/common -I$(SDKSRC)/pm_shared -I$(SDKSRC)/dlls -I$(SDKSRC)
|
|
||||||
FILES_ALL = *.cpp *.h [A-Z]* *.rc
|
|
||||||
|
|
||||||
CFLAGS=-Wall -Wno-unknown-pragmas -Wno-attributes -Wno-write-strings
|
|
||||||
|
|
||||||
CFLAGS+=-std=gnu++98 -Wno-c++11-compat
|
|
||||||
|
|
||||||
#CFLAGS += -DTEST
|
|
||||||
|
|
||||||
ifeq "$(OPT)" "opt-fast"
|
|
||||||
ODEF = -DOPT_TYPE="\"optimized+meta_debug-disabled\""
|
|
||||||
CFLAGS := $(CCOPT) $(CFLAGS) $(ODEF) -D__BUILD_FAST_METAMOD__
|
|
||||||
OBJDIR_LINUX = $(OBJDIR_LINUX_OPT)
|
|
||||||
OBJDIR_WIN = $(OBJDIR_WIN_OPT)
|
|
||||||
else #other
|
|
||||||
ifeq "$(OPT)" "opt"
|
|
||||||
ODEF = -DOPT_TYPE="\"optimized\""
|
|
||||||
CFLAGS := $(CCOPT) $(CFLAGS) $(ODEF)
|
|
||||||
OBJDIR_LINUX = $(OBJDIR_LINUX_OPT)
|
|
||||||
OBJDIR_WIN = $(OBJDIR_WIN_OPT)
|
|
||||||
else # debug
|
|
||||||
ODEF = -DOPT_TYPE="\"debugging\""
|
|
||||||
CFLAGS := $(CCDEBUG) $(CFLAGS) $(ODEF)
|
|
||||||
OBJDIR_LINUX = $(OBJDIR_LINUX_DBG)
|
|
||||||
OBJDIR_WIN = $(OBJDIR_WIN_DBG)
|
|
||||||
DLLS_DIR := $(DLLS_DIR)/debug
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq "$(OS)" "linux"
|
|
||||||
OBJDIR = $(OBJDIR_LINUX)
|
|
||||||
else
|
|
||||||
OBJDIR = $(OBJDIR_WIN)
|
|
||||||
endif
|
|
||||||
|
|
||||||
include Config.mak
|
|
||||||
# any local CFLAGS from Config.mak
|
|
||||||
CFLAGS += $(EXTRA_CFLAGS)
|
|
||||||
|
|
||||||
# provide timezone info
|
|
||||||
$(OBJDIR_LINUX)/vdate.o $(OBJDIR_WIN)/vdate.o: CFLAGS += -DCOMPILE_TZ=\"$(COMPILE_TZ)\"
|
|
||||||
|
|
||||||
# ignore complaints from SDK files like cbase.h
|
|
||||||
#$(OBJDIR_LINUX)/sdk_util.o $(OBJDIR_WIN)/sdk_util.o: CFLAGS += -Wno-unused
|
|
||||||
|
|
||||||
# ignore complaints from STL headers
|
|
||||||
STLOBJ = $(STLFILES:%.cpp=$(OBJDIR_LINUX)/%.o)
|
|
||||||
STLOBJ += $(STLFILES:%.cpp=$(OBJDIR_WIN)/%.o)
|
|
||||||
#$(OBJDIR_LINUX)/mreg.o $(OBJDIR_WIN)/mreg.o: CFLAGS += -Wno-effc++
|
|
||||||
$(STLOBJ): FILTER= 2>&1 | ../tools/stlfilter
|
|
||||||
$(STLOBJ): CFLAGS += -Wno-error
|
|
||||||
|
|
||||||
# these files seem to create "Internal compiler error" errors under mingw
|
|
||||||
# when using -O6
|
|
||||||
#$(OBJDIR_WIN)/engine_api.o: CCO = -O5
|
|
||||||
#$(OBJDIR_WIN)/dllapi_api.o: CCO = -O5
|
|
||||||
|
|
||||||
#############################################################################
|
|
||||||
# BUILDING LINUX SO
|
|
||||||
#############################################################################
|
|
||||||
|
|
||||||
# linux .so compile commands
|
|
||||||
DO_CC_LINUX=$(CC) $(CFLAGS) -fPIC $(INCLUDEDIRS) -o $@ -c $< $(FILTER)
|
|
||||||
LINK_LINUX=$(CC) $(CFLAGS) -shared -ldl -lm -static-libgcc $(EXTRA_LINK) $(OBJ_LINUX) -o $@
|
|
||||||
|
|
||||||
# sort by date
|
|
||||||
#SRCFILES := $(shell ls -t $(SRCFILES))
|
|
||||||
|
|
||||||
# linux object files
|
|
||||||
OBJ_LINUX := $(SRCFILES:%.cpp=$(OBJDIR_LINUX)/%.o)
|
|
||||||
|
|
||||||
# compiling linux object files
|
|
||||||
$(OBJDIR_LINUX)/%.o: $(SRCDIR)/%.cpp
|
|
||||||
$(DO_CC_LINUX)
|
|
||||||
|
|
||||||
# linux .so target file
|
|
||||||
LIBFILE_LINUX = $(MODNAME).so
|
|
||||||
TARGET_LINUX = $(OBJDIR_LINUX)/$(LIBFILE_LINUX)
|
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
|
||||||
# BUILDING WINDOWS DLL
|
|
||||||
#############################################################################
|
|
||||||
|
|
||||||
# windows .dll compile commands
|
|
||||||
DO_CC_WIN=$(CC_WIN) $(CFLAGS) $(INCLUDEDIRS) -o $@ -c $<
|
|
||||||
DO_RES_WIN=$(RES_WIN) '$(ODEF)' --include-dir . --include-dir ../metamod -i $< -O coff -o $@
|
|
||||||
#LINK_WIN=$(LD_WINDLL) -k -mwindows --add-stdcall-alias --def metamod.def -o $@ $(OBJ_WIN)
|
|
||||||
#LINK_WIN=$(LD_WINDLL) -A -k -mwindows --export-all-symbols -o $@ $(OBJ_WIN)
|
|
||||||
#LINK_WIN=$(LD_WINDLL) -mwindows --add-stdcall-alias $(OBJ_WIN) $(RES_OBJ_WIN) -lstdc++ -s -o $@
|
|
||||||
LINK_WIN=$(CC_WIN) $(CFLAGS) -mdll -Xlinker --add-stdcall-alias $(EXTRA_LINK) $(OBJ_WIN) $(RES_OBJ_WIN) -s -o $@
|
|
||||||
|
|
||||||
# windows object files
|
|
||||||
OBJ_WIN := $(SRCFILES:%.cpp=$(OBJDIR_WIN)/%.o)
|
|
||||||
RES_OBJ_WIN := $(RESFILE:%.rc=$(OBJDIR_WIN)/%.o)
|
|
||||||
|
|
||||||
# compiling windows object files
|
|
||||||
$(OBJDIR_WIN)/%.o: $(SRCDIR)/%.cpp
|
|
||||||
$(DO_CC_WIN)
|
|
||||||
|
|
||||||
# compiling windows resource file
|
|
||||||
$(OBJDIR_WIN)/%.o: $(SRCDIR)/%.rc $(INFOFILES)
|
|
||||||
$(DO_RES_WIN)
|
|
||||||
|
|
||||||
# windows .dll target file
|
|
||||||
LIBFILE_WIN = $(MODNAME).dll
|
|
||||||
TARGET_WIN = $(OBJDIR_WIN)/$(LIBFILE_WIN)
|
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
|
||||||
# OVERRIDES
|
|
||||||
#############################################################################
|
|
||||||
|
|
||||||
ifeq "$(PLATFORM)" "linux-only"
|
|
||||||
LIBFILE_WIN =
|
|
||||||
TARGET_WIN =
|
|
||||||
endif
|
|
||||||
ifeq "$(PLATFORM)" "win32-only"
|
|
||||||
LIBFILE_LINUX =
|
|
||||||
TARGET_LINUX =
|
|
||||||
OSTARGET=win32
|
|
||||||
LIBFILE=$(LIBFILE_WIN)
|
|
||||||
TARGET_FILE=$(TARGET_WIN)
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
#############################################################################
|
|
||||||
# BUILD RULES
|
|
||||||
#############################################################################
|
|
||||||
|
|
||||||
default: $(TARGET_FILE)
|
|
||||||
|
|
||||||
all: do_dll_linux do_dll_win32
|
|
||||||
|
|
||||||
opt:
|
|
||||||
$(MAKE) default OPT=opt
|
|
||||||
|
|
||||||
linux: do_dll_linux
|
|
||||||
win32: do_dll_win32
|
|
||||||
|
|
||||||
linux_opt:
|
|
||||||
$(MAKE) linux OPT=opt
|
|
||||||
win32_opt:
|
|
||||||
$(MAKE) win32 OPT=opt
|
|
||||||
|
|
||||||
$(TARGET_LINUX): msgs/debug msgs/warning msgs/log msgs/error $(OBJDIR_LINUX) $(OBJ_LINUX)
|
|
||||||
$(LINK_LINUX)
|
|
||||||
|
|
||||||
# for plugins, recompile meta_api.cpp if info_name.h changed
|
|
||||||
$(OBJDIR_LINUX)/meta_api.o $(OBJDIR_WIN)/meta_api.o: info_name.h
|
|
||||||
|
|
||||||
$(TARGET_WIN): msgs/debug msgs/warning msgs/log msgs/error $(OBJDIR_WIN) $(OBJ_WIN) $(RES_OBJ_WIN)
|
|
||||||
$(LINK_WIN)
|
|
||||||
|
|
||||||
$(OBJDIR_LINUX) $(OBJDIR_WIN) msgs:
|
|
||||||
mkdir $@
|
|
||||||
|
|
||||||
# make sure to recompile vdate.c for each link
|
|
||||||
$(OBJDIR_LINUX)/vdate.o $(OBJDIR_WIN)/vdate.o : $(SRCFILES) *.h
|
|
||||||
|
|
||||||
domsgs: msgs/debug msgs/log msgs/error msgs/warning
|
|
||||||
|
|
||||||
msgs/debug: $(SRCFILES) *.h msgs
|
|
||||||
egrep "DEBUG\([0-9]" $(SRCFILES) *.h | sed "s/:[ ]*/ /" | sort -k2,2 > $@
|
|
||||||
|
|
||||||
msgs/log: $(SRCFILES) *.h msgs
|
|
||||||
egrep "META_LOG\(" $(SRCFILES) *.h | sed "s/:[ ]*/ /" | sort > $@
|
|
||||||
|
|
||||||
msgs/error: $(SRCFILES) *.h msgs
|
|
||||||
egrep "META_ERROR\(" $(SRCFILES) *.h | sed "s/:[ ]*/ /" | sort > $@
|
|
||||||
|
|
||||||
msgs/warning: $(SRCFILES) *.h msgs
|
|
||||||
egrep "META_WARNING\(" $(SRCFILES) *.h | sed "s/:[ ]*/ /" | sort > $@
|
|
||||||
|
|
||||||
tags: .tags .htags
|
|
||||||
ctags: .tags
|
|
||||||
htags: .htags
|
|
||||||
|
|
||||||
.tags: $(SRCFILES) *.h
|
|
||||||
-ctags -a $?
|
|
||||||
|
|
||||||
.htags: *.h
|
|
||||||
-htags $?
|
|
||||||
|
|
||||||
retags:
|
|
||||||
-rm -f .tags .htags
|
|
||||||
ctags -f .tags `find $(SDKSRC) -name '*.h'`
|
|
||||||
ctags -f .tags -a `find $(METADIR) -name old -prune -o -name '*.h' -print`
|
|
||||||
ctags -f .tags -a $(SRCFILES)
|
|
||||||
htags -R $(SDKSRC)
|
|
||||||
htags `find $(METADIR) -name old -prune -o -name '*.h' -print`
|
|
||||||
htags *.h
|
|
||||||
|
|
||||||
clean: clean_$(OSTARGET)
|
|
||||||
|
|
||||||
clean_linux:
|
|
||||||
test -n "$(OBJDIR_LINUX)"
|
|
||||||
-rm -f $(OBJDIR_LINUX)/*
|
|
||||||
|
|
||||||
clean_win32:
|
|
||||||
test -n "$(OBJDIR_WIN)"
|
|
||||||
-rm -f $(OBJDIR_WIN)/*
|
|
||||||
|
|
||||||
cleanall_linux:
|
|
||||||
$(MAKE) clean_linux
|
|
||||||
$(MAKE) clean_linux OPT=opt
|
|
||||||
$(MAKE) clean_linux TARGET=amd64
|
|
||||||
$(MAKE) clean_linux TARGET=amd64 OPT=opt
|
|
||||||
|
|
||||||
cleanall_win32:
|
|
||||||
$(MAKE) clean_win32
|
|
||||||
$(MAKE) clean_win32 OPT=opt
|
|
||||||
|
|
||||||
cleanall: cleanall_linux cleanall_win32
|
|
||||||
|
|
||||||
dll_linux dll_win32:
|
|
||||||
$(MAKE) do_$@
|
|
||||||
$(MAKE) do_$@ OPT=opt
|
|
||||||
|
|
||||||
do_dll_linux: $(DLLS_DIR) $(DLLS_DIR)/$(LIBFILE_LINUX)
|
|
||||||
do_dll_win32: $(DLLS_DIR) $(DLLS_DIR)/$(LIBFILE_WIN)
|
|
||||||
|
|
||||||
$(DLLS_DIR):
|
|
||||||
mkdir $(DLLS_DIR)
|
|
||||||
|
|
||||||
$(DLLS_DIR)/$(LIBFILE_LINUX): $(TARGET_LINUX)
|
|
||||||
$(INSTALL) $+ $@
|
|
||||||
|
|
||||||
$(DLLS_DIR)/$(LIBFILE_WIN): $(TARGET_WIN)
|
|
||||||
$(INSTALL) $+ $@
|
|
||||||
|
|
||||||
dlls: dll_linux dll_win32
|
|
||||||
rmdlls:
|
|
||||||
-rm -f ../dlls/*.* ../dlls/debug/*.*
|
|
||||||
|
|
||||||
spotless: cleanall
|
|
||||||
-rmdir $(OBJDIR_LINUX) $(OBJDIR_WIN)
|
|
||||||
# -rm -f .snap $(GENERATED)
|
|
||||||
|
|
||||||
distclean: spotless
|
|
||||||
|
|
||||||
install: $(INST_DIR)/$(LIBFILE)
|
|
||||||
test: $(TEST_DIR)/$(LIBFILE)
|
|
||||||
test_opt:
|
|
||||||
$(MAKE) test OPT=opt
|
|
||||||
|
|
||||||
$(INST_DIR)/$(LIBFILE) $(TEST_DIR)/$(LIBFILE): $(TARGET_FILE)
|
|
||||||
$(INSTALL) $< $@
|
|
||||||
|
|
||||||
tst: $(TST_DIR)/$(LIBFILE_WIN)
|
|
||||||
|
|
||||||
$(TST_DIR)/$(LIBFILE_WIN): $(TARGET_WIN)
|
|
||||||
cp $< $@
|
|
||||||
|
|
||||||
snap: .snap
|
|
||||||
|
|
||||||
.snap: $(FILES_ALL)
|
|
||||||
mkdir -p snapshots
|
|
||||||
tar zcvf snapshots/`date '+%m%d-%H%M'`.tgz $(FILES_ALL)
|
|
||||||
touch .snap
|
|
||||||
|
|
||||||
depend: $(OBJDIR)/Rules.depend
|
|
||||||
|
|
||||||
$(OBJDIR)/Rules.depend: Makefile $(SRCFILES) $(OBJDIR)
|
|
||||||
$(CC_DEP) -MM $(INCLUDEDIRS) $(SRCFILES) | sed "s;\(^[^ ]*\):\(.*\);$(OBJDIR)/\1: Makefile Config.mak \2;" > $@
|
|
||||||
|
|
||||||
include $(OBJDIR)/Rules.depend
|
|
||||||
@@ -1,690 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
|
||||||
*
|
|
||||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stddef.h> // offsetof
|
|
||||||
#include <extdll.h>
|
|
||||||
|
|
||||||
#include "ret_type.h"
|
|
||||||
#include "types_meta.h"
|
|
||||||
#include "api_info.h"
|
|
||||||
#include "api_hook.h"
|
|
||||||
#include "mplugin.h"
|
|
||||||
#include "metamod.h"
|
|
||||||
#include "osdep.h" //unlikely
|
|
||||||
|
|
||||||
// getting pointer with table index is faster than with if-else
|
|
||||||
static const void ** api_tables[3] = {
|
|
||||||
(const void**)&Engine.funcs,
|
|
||||||
(const void**)&GameDLL.funcs.dllapi_table,
|
|
||||||
(const void**)&GameDLL.funcs.newapi_table
|
|
||||||
};
|
|
||||||
|
|
||||||
static const void ** api_info_tables[3] = {
|
|
||||||
(const void**)&engine_info,
|
|
||||||
(const void**)&dllapi_info,
|
|
||||||
(const void**)&newapi_info
|
|
||||||
};
|
|
||||||
|
|
||||||
// Safety check for metamod-bot-plugin bugfix.
|
|
||||||
// engine_api->pfnRunPlayerMove calls dllapi-functions before it returns.
|
|
||||||
// This causes problems with bots running as metamod plugins, because
|
|
||||||
// metamod assumed that PublicMetaGlobals is free to be used.
|
|
||||||
// With call_count we can fix this by backuping up PublicMetaGlobals if
|
|
||||||
// it's already being used.
|
|
||||||
static unsigned int call_count = 0;
|
|
||||||
|
|
||||||
// get function pointer from api table by function pointer offset
|
|
||||||
inline void * DLLINTERNAL get_api_function(const void * api_table, unsigned int func_offset) {
|
|
||||||
return(*(void**)((unsigned long)api_table + func_offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
// get data pointer from api_info table by function offset
|
|
||||||
inline const api_info_t * DLLINTERNAL get_api_info(enum_api_t api, unsigned int api_info_offset) {
|
|
||||||
return((const api_info_t *)((unsigned long)api_info_tables[api] + api_info_offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
// simplified 'void' version of main hook function
|
|
||||||
void DLLINTERNAL main_hook_function_void(unsigned int api_info_offset, enum_api_t api, unsigned int func_offset, const void * packed_args) {
|
|
||||||
const api_info_t *api_info;
|
|
||||||
int i;
|
|
||||||
META_RES mres, status, prev_mres;
|
|
||||||
MPlugin *iplug;
|
|
||||||
void *pfn_routine;
|
|
||||||
int loglevel;
|
|
||||||
const void *api_table;
|
|
||||||
meta_globals_t backup_meta_globals[1];
|
|
||||||
|
|
||||||
//passing offset from api wrapper function makes code faster/smaller
|
|
||||||
api_info = get_api_info(api, api_info_offset);
|
|
||||||
|
|
||||||
//Fix bug with metamod-bot-plugins.
|
|
||||||
if(unlikely(call_count++>0)) {
|
|
||||||
//Backup PublicMetaGlobals.
|
|
||||||
backup_meta_globals[0] = PublicMetaGlobals;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Setup
|
|
||||||
loglevel=api_info->loglevel;
|
|
||||||
mres=MRES_UNSET;
|
|
||||||
status=MRES_UNSET;
|
|
||||||
prev_mres=MRES_UNSET;
|
|
||||||
pfn_routine=NULL;
|
|
||||||
|
|
||||||
//Pre plugin functions
|
|
||||||
prev_mres=MRES_UNSET;
|
|
||||||
for(i=0; likely(i < Plugins->endlist); i++) {
|
|
||||||
iplug=&Plugins->plist[i];
|
|
||||||
|
|
||||||
if(unlikely(iplug->status != PL_RUNNING))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
api_table = iplug->get_api_table(api);
|
|
||||||
if(likely(!api_table)) {
|
|
||||||
//plugin doesn't provide this api table
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pfn_routine=get_api_function(api_table, func_offset);
|
|
||||||
if(likely(!pfn_routine)) {
|
|
||||||
//plugin doesn't provide this function
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize PublicMetaGlobals
|
|
||||||
PublicMetaGlobals.mres = MRES_UNSET;
|
|
||||||
PublicMetaGlobals.prev_mres = prev_mres;
|
|
||||||
PublicMetaGlobals.status = status;
|
|
||||||
|
|
||||||
// call plugin
|
|
||||||
META_DEBUG(loglevel, ("Calling %s:%s()", iplug->file, api_info->name));
|
|
||||||
api_info->api_caller(pfn_routine, packed_args);
|
|
||||||
API_UNPAUSE_TSC_TRACKING();
|
|
||||||
|
|
||||||
// plugin's result code
|
|
||||||
mres=PublicMetaGlobals.mres;
|
|
||||||
if(unlikely(mres > status))
|
|
||||||
status = mres;
|
|
||||||
|
|
||||||
// save this for successive plugins to see
|
|
||||||
prev_mres = mres;
|
|
||||||
|
|
||||||
if(unlikely(mres==MRES_UNSET))
|
|
||||||
META_WARNING("Plugin didn't set meta_result: %s:%s()", iplug->file, api_info->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
call_count--;
|
|
||||||
|
|
||||||
//Api call
|
|
||||||
if(likely(status!=MRES_SUPERCEDE)) {
|
|
||||||
//get api table
|
|
||||||
api_table = *api_tables[api];
|
|
||||||
|
|
||||||
if(likely(api_table)) {
|
|
||||||
pfn_routine = get_api_function(api_table, func_offset);
|
|
||||||
if(likely(pfn_routine)) {
|
|
||||||
META_DEBUG(loglevel, ("Calling %s:%s()", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
|
||||||
api_info->api_caller(pfn_routine, packed_args);
|
|
||||||
API_UNPAUSE_TSC_TRACKING();
|
|
||||||
} else {
|
|
||||||
// don't complain for NULL routines in NEW_DLL_FUNCTIONS
|
|
||||||
if(unlikely(api != e_api_newapi))
|
|
||||||
META_WARNING("Couldn't find api call: %s:%s", (api==e_api_engine)?"engine":GameDLL.file, api_info->name);
|
|
||||||
status=MRES_UNSET;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// don't complain for NULL NEW_DLL_FUNCTIONS-table
|
|
||||||
if(unlikely(api != e_api_newapi))
|
|
||||||
META_DEBUG(loglevel, ("No api table defined for api call: %s:%s", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
|
||||||
status=MRES_UNSET;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
META_DEBUG(loglevel, ("Skipped (supercede) %s:%s()", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
|
||||||
|
|
||||||
call_count++;
|
|
||||||
|
|
||||||
//Post plugin functions
|
|
||||||
prev_mres=MRES_UNSET;
|
|
||||||
for(i=0; likely(i < Plugins->endlist); i++) {
|
|
||||||
iplug=&Plugins->plist[i];
|
|
||||||
|
|
||||||
if(unlikely(iplug->status != PL_RUNNING))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
api_table = iplug->get_api_post_table(api);
|
|
||||||
if(likely(!api_table)) {
|
|
||||||
//plugin doesn't provide this api table
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pfn_routine=get_api_function(api_table, func_offset);
|
|
||||||
if(likely(!pfn_routine)) {
|
|
||||||
//plugin doesn't provide this function
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize PublicMetaGlobals
|
|
||||||
PublicMetaGlobals.mres = MRES_UNSET;
|
|
||||||
PublicMetaGlobals.prev_mres = prev_mres;
|
|
||||||
PublicMetaGlobals.status = status;
|
|
||||||
|
|
||||||
// call plugin
|
|
||||||
META_DEBUG(loglevel, ("Calling %s:%s_Post()", iplug->file, api_info->name));
|
|
||||||
api_info->api_caller(pfn_routine, packed_args);
|
|
||||||
API_UNPAUSE_TSC_TRACKING();
|
|
||||||
|
|
||||||
// plugin's result code
|
|
||||||
mres=PublicMetaGlobals.mres;
|
|
||||||
if(unlikely(mres > status))
|
|
||||||
status = mres;
|
|
||||||
|
|
||||||
// save this for successive plugins to see
|
|
||||||
prev_mres = mres;
|
|
||||||
|
|
||||||
if(unlikely(mres==MRES_UNSET))
|
|
||||||
META_WARNING("Plugin didn't set meta_result: %s:%s_Post()", iplug->file, api_info->name);
|
|
||||||
else if(unlikely(mres==MRES_SUPERCEDE))
|
|
||||||
META_WARNING("MRES_SUPERCEDE not valid in Post functions: %s:%s_Post()", iplug->file, api_info->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(unlikely(--call_count>0)) {
|
|
||||||
//Restore backup
|
|
||||||
PublicMetaGlobals = backup_meta_globals[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// full return typed version of main hook function
|
|
||||||
void * DLLINTERNAL main_hook_function(const class_ret_t ret_init, unsigned int api_info_offset, enum_api_t api, unsigned int func_offset, const void * packed_args) {
|
|
||||||
const api_info_t *api_info;
|
|
||||||
int i;
|
|
||||||
META_RES mres, status, prev_mres;
|
|
||||||
MPlugin *iplug;
|
|
||||||
void *pfn_routine;
|
|
||||||
int loglevel;
|
|
||||||
const void *api_table;
|
|
||||||
meta_globals_t backup_meta_globals[1];
|
|
||||||
|
|
||||||
//passing offset from api wrapper function makes code faster/smaller
|
|
||||||
api_info = get_api_info(api, api_info_offset);
|
|
||||||
|
|
||||||
//Fix bug with metamod-bot-plugins.
|
|
||||||
if(unlikely(call_count++>0)) {
|
|
||||||
//Backup PublicMetaGlobals.
|
|
||||||
backup_meta_globals[0] = PublicMetaGlobals;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Return class setup
|
|
||||||
class_ret_t dllret=ret_init;
|
|
||||||
class_ret_t override_ret=ret_init;
|
|
||||||
class_ret_t pub_override_ret=ret_init;
|
|
||||||
class_ret_t orig_ret=ret_init;
|
|
||||||
class_ret_t pub_orig_ret=ret_init;
|
|
||||||
|
|
||||||
//Setup
|
|
||||||
loglevel=api_info->loglevel;
|
|
||||||
mres=MRES_UNSET;
|
|
||||||
status=MRES_UNSET;
|
|
||||||
prev_mres=MRES_UNSET;
|
|
||||||
pfn_routine=NULL;
|
|
||||||
|
|
||||||
//Pre plugin functions
|
|
||||||
prev_mres=MRES_UNSET;
|
|
||||||
for(i=0; likely(i < Plugins->endlist); i++) {
|
|
||||||
iplug=&Plugins->plist[i];
|
|
||||||
|
|
||||||
if(unlikely(iplug->status != PL_RUNNING))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
api_table = iplug->get_api_table(api);
|
|
||||||
if(likely(!api_table)) {
|
|
||||||
//plugin doesn't provide this api table
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pfn_routine=get_api_function(api_table, func_offset);
|
|
||||||
if(likely(!pfn_routine)) {
|
|
||||||
//plugin doesn't provide this function
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize PublicMetaGlobals
|
|
||||||
PublicMetaGlobals.mres = MRES_UNSET;
|
|
||||||
PublicMetaGlobals.prev_mres = prev_mres;
|
|
||||||
PublicMetaGlobals.status = status;
|
|
||||||
pub_orig_ret = orig_ret;
|
|
||||||
PublicMetaGlobals.orig_ret = pub_orig_ret.getptr();
|
|
||||||
if(unlikely(status==MRES_SUPERCEDE)) {
|
|
||||||
pub_override_ret = override_ret;
|
|
||||||
PublicMetaGlobals.override_ret = pub_override_ret.getptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
// call plugin
|
|
||||||
META_DEBUG(loglevel, ("Calling %s:%s()", iplug->file, api_info->name));
|
|
||||||
dllret = class_ret_t(api_info->api_caller(pfn_routine, packed_args));
|
|
||||||
API_UNPAUSE_TSC_TRACKING();
|
|
||||||
|
|
||||||
// plugin's result code
|
|
||||||
mres=PublicMetaGlobals.mres;
|
|
||||||
if(unlikely(mres > status))
|
|
||||||
status = mres;
|
|
||||||
|
|
||||||
// save this for successive plugins to see
|
|
||||||
prev_mres = mres;
|
|
||||||
|
|
||||||
if(unlikely(mres==MRES_SUPERCEDE)) {
|
|
||||||
pub_override_ret = dllret;
|
|
||||||
override_ret = dllret;
|
|
||||||
}
|
|
||||||
else if(unlikely(mres==MRES_UNSET)) {
|
|
||||||
META_WARNING("Plugin didn't set meta_result: %s:%s()", iplug->file, api_info->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
call_count--;
|
|
||||||
|
|
||||||
//Api call
|
|
||||||
if(likely(status!=MRES_SUPERCEDE)) {
|
|
||||||
//get api table
|
|
||||||
api_table = *api_tables[api];
|
|
||||||
|
|
||||||
if(likely(api_table)) {
|
|
||||||
pfn_routine = get_api_function(api_table, func_offset);
|
|
||||||
if(likely(pfn_routine)) {
|
|
||||||
META_DEBUG(loglevel, ("Calling %s:%s()", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
|
||||||
dllret = class_ret_t(api_info->api_caller(pfn_routine, packed_args));
|
|
||||||
API_UNPAUSE_TSC_TRACKING();
|
|
||||||
orig_ret = dllret;
|
|
||||||
} else {
|
|
||||||
// don't complain for NULL routines in NEW_DLL_FUNCTIONS
|
|
||||||
if(unlikely(api != e_api_newapi))
|
|
||||||
META_WARNING("Couldn't find api call: %s:%s", (api==e_api_engine)?"engine":GameDLL.file, api_info->name);
|
|
||||||
status=MRES_UNSET;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// don't complain for NULL NEW_DLL_FUNCTIONS-table
|
|
||||||
if(unlikely(api != e_api_newapi))
|
|
||||||
META_DEBUG(loglevel, ("No api table defined for api call: %s:%s", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
|
||||||
status=MRES_UNSET;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
META_DEBUG(loglevel, ("Skipped (supercede) %s:%s()", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
|
||||||
orig_ret = override_ret;
|
|
||||||
pub_orig_ret = override_ret;
|
|
||||||
PublicMetaGlobals.orig_ret = pub_orig_ret.getptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
call_count++;
|
|
||||||
|
|
||||||
//Pre plugin functions
|
|
||||||
prev_mres=MRES_UNSET;
|
|
||||||
for(i=0; likely(i < Plugins->endlist); i++) {
|
|
||||||
iplug=&Plugins->plist[i];
|
|
||||||
|
|
||||||
if(unlikely(iplug->status != PL_RUNNING))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
api_table = iplug->get_api_post_table(api);
|
|
||||||
if(likely(!api_table)) {
|
|
||||||
//plugin doesn't provide this api table
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
pfn_routine=get_api_function(api_table, func_offset);
|
|
||||||
if(likely(!pfn_routine)) {
|
|
||||||
//plugin doesn't provide this function
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize PublicMetaGlobals
|
|
||||||
PublicMetaGlobals.mres = MRES_UNSET;
|
|
||||||
PublicMetaGlobals.prev_mres = prev_mres;
|
|
||||||
PublicMetaGlobals.status = status;
|
|
||||||
pub_orig_ret = orig_ret;
|
|
||||||
PublicMetaGlobals.orig_ret = pub_orig_ret.getptr();
|
|
||||||
if(unlikely(status==MRES_OVERRIDE)) {
|
|
||||||
pub_override_ret = override_ret;
|
|
||||||
PublicMetaGlobals.override_ret = pub_override_ret.getptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
// call plugin
|
|
||||||
META_DEBUG(loglevel, ("Calling %s:%s_Post()", iplug->file, api_info->name));
|
|
||||||
dllret = class_ret_t(api_info->api_caller(pfn_routine, packed_args));
|
|
||||||
API_UNPAUSE_TSC_TRACKING();
|
|
||||||
|
|
||||||
// plugin's result code
|
|
||||||
mres=PublicMetaGlobals.mres;
|
|
||||||
if(unlikely(mres > status))
|
|
||||||
status = mres;
|
|
||||||
|
|
||||||
// save this for successive plugins to see
|
|
||||||
prev_mres = mres;
|
|
||||||
|
|
||||||
if(unlikely(mres==MRES_OVERRIDE)) {
|
|
||||||
pub_override_ret = dllret;
|
|
||||||
override_ret = dllret;
|
|
||||||
}
|
|
||||||
else if(unlikely(mres==MRES_UNSET)) {
|
|
||||||
META_WARNING("Plugin didn't set meta_result: %s:%s_Post()", iplug->file, api_info->name);
|
|
||||||
}
|
|
||||||
else if(unlikely(mres==MRES_SUPERCEDE)) {
|
|
||||||
META_WARNING("MRES_SUPERCEDE not valid in Post functions: %s:%s_Post()", iplug->file, api_info->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(unlikely(--call_count>0)) {
|
|
||||||
//Restore backup
|
|
||||||
PublicMetaGlobals = backup_meta_globals[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
//return value is passed through ret_init!
|
|
||||||
if(likely(status!=MRES_OVERRIDE)) {
|
|
||||||
return(*(void**)orig_ret.getptr());
|
|
||||||
} else {
|
|
||||||
META_DEBUG(loglevel, ("Returning (override) %s()", api_info->name));
|
|
||||||
return(*(void**)override_ret.getptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Macros for creating api caller functions
|
|
||||||
//
|
|
||||||
#define BEGIN_API_CALLER_FUNC(ret_type, args_type_code) \
|
|
||||||
void * DLLINTERNAL _COMBINE4(api_caller_, ret_type, _args_, args_type_code)(const void * func, const void * packed_args) { \
|
|
||||||
_COMBINE2(pack_args_type_, args_type_code) * p ATTRIBUTE(unused)= (_COMBINE2(pack_args_type_, args_type_code) *)packed_args;
|
|
||||||
#define END_API_CALLER_FUNC(ret_t, args_t, args) \
|
|
||||||
API_PAUSE_TSC_TRACKING(); \
|
|
||||||
return(*(void **)class_ret_t((*(( ret_t (*) args_t )func)) args).getptr()); \
|
|
||||||
}
|
|
||||||
#define END_API_CALLER_FUNC_void(args_t, args) \
|
|
||||||
API_PAUSE_TSC_TRACKING(); \
|
|
||||||
return((*(( void* (*) args_t )func)) args); \
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// API function callers.
|
|
||||||
//
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, ipV)
|
|
||||||
END_API_CALLER_FUNC_void( (int, const void*, ...), (p->i1, p->p1, p->str) )
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 2pV)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*, ...), (p->p1, p->p2, p->str) )
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, void)
|
|
||||||
END_API_CALLER_FUNC_void( (void), () )
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(ptr, void)
|
|
||||||
END_API_CALLER_FUNC(void*, (void), () )
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(int, void)
|
|
||||||
END_API_CALLER_FUNC(int, (void), () )
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(float, void)
|
|
||||||
END_API_CALLER_FUNC(float, (void), () )
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(float, 2f)
|
|
||||||
END_API_CALLER_FUNC( float, (float, float), (p->f1, p->f2) )
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 2i)
|
|
||||||
END_API_CALLER_FUNC_void( (int, int), (p->i1, p->i2) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(int, 2i)
|
|
||||||
END_API_CALLER_FUNC(int, (int, int), (p->i1, p->i2) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 2i2p)
|
|
||||||
END_API_CALLER_FUNC_void( (int, int, const void*, const void*), (p->i1, p->i2, p->p1, p->p2) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 2i2pi2p)
|
|
||||||
END_API_CALLER_FUNC_void( (int, int, const void*, const void*, int, const void*, const void*), (p->i1, p->i2, p->p1, p->p2, p->i3, p->p3, p->p4) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 2p)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*), (p->p1, p->p2) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(ptr, 2p)
|
|
||||||
END_API_CALLER_FUNC(void*, (const void*, const void*), (p->p1, p->p2) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(int, 2p)
|
|
||||||
END_API_CALLER_FUNC(int, (const void*, const void*), (p->p1, p->p2) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 2p2f)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*, float, float), (p->p1, p->p2, p->f1, p->f2) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 2p2i2p)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*, int, int, const void*, const void*), (p->p1, p->p2, p->i1, p->i2, p->p3, p->p4) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 2p3fus2uc)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*, float, float, float, unsigned short, unsigned char, unsigned char), (p->p1, p->p2, p->f1, p->f2, p->f3, p->us1, p->uc1, p->uc2) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(ptr, 2pf)
|
|
||||||
END_API_CALLER_FUNC(void*, (const void*, const void*, float), (p->p1, p->p2, p->f1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 2pfi)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*, float, int), (p->p1, p->p2, p->f1, p->i1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 2pi)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*, int), (p->p1, p->p2, p->i1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(int, 2pi)
|
|
||||||
END_API_CALLER_FUNC(int, (const void*, const void*, int), (p->p1, p->p2, p->i1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 2pui)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*, unsigned int), (p->p1, p->p2, p->ui1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 2pi2p)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*, int, const void*, const void*), (p->p1, p->p2, p->i1, p->p3, p->p4) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 2pif2p)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*, int, float, const void*, const void*), (p->p1, p->p2, p->i1, p->f1, p->p3, p->p4) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(int, 3i)
|
|
||||||
END_API_CALLER_FUNC(int, (int, int, int), (p->i1, p->i2, p->i3) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 3p)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*, const void*), (p->p1, p->p2, p->p3) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(ptr, 3p)
|
|
||||||
END_API_CALLER_FUNC(void*, (const void*, const void*, const void*), (p->p1, p->p2, p->p3) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(int, 3p)
|
|
||||||
END_API_CALLER_FUNC(int, (const void*, const void*, const void*), (p->p1, p->p2, p->p3) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 3p2f2i)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*, const void*, float, float, int, int), (p->p1, p->p2, p->p3, p->f1, p->f2, p->i1, p->i2) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(int, 3pi2p)
|
|
||||||
END_API_CALLER_FUNC(int, (const void*, const void*, const void*, int, const void*, const void*), (p->p1, p->p2, p->p3, p->i1, p->p4, p->p5) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 4p)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*, const void*, const void*), (p->p1, p->p2, p->p3, p->p4) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(int, 4p)
|
|
||||||
END_API_CALLER_FUNC(int, (const void*, const void*, const void*, const void*), (p->p1, p->p2, p->p3, p->p4) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, 4pi)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, const void*, const void*, const void*, int), (p->p1, p->p2, p->p3, p->p4, p->i1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(int, 4pi)
|
|
||||||
END_API_CALLER_FUNC(int, (const void*, const void*, const void*, const void*, int), (p->p1, p->p2, p->p3, p->p4, p->i1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, f)
|
|
||||||
END_API_CALLER_FUNC_void( (float), (p->f1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, i)
|
|
||||||
END_API_CALLER_FUNC_void( (int), (p->i1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(int, i)
|
|
||||||
END_API_CALLER_FUNC(int, (int), (p->i1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(ptr, i)
|
|
||||||
END_API_CALLER_FUNC(void*, (int), (p->i1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(uint, ui)
|
|
||||||
END_API_CALLER_FUNC(unsigned int, (unsigned int), (p->ui1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(ptr, ui)
|
|
||||||
END_API_CALLER_FUNC(void*, (unsigned int), (p->ui1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(ulong, ul)
|
|
||||||
END_API_CALLER_FUNC(unsigned long, (unsigned long), (p->ul1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, i2p)
|
|
||||||
END_API_CALLER_FUNC_void( (int, const void*, const void*), (p->i1, p->p1, p->p2) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(int, i2p)
|
|
||||||
END_API_CALLER_FUNC(int, (int, const void*, const void*), (p->i1, p->p1, p->p2) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, i3p)
|
|
||||||
END_API_CALLER_FUNC_void( (int, const void*, const void*, const void*), (p->i1, p->p1, p->p2, p->p3) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, ip)
|
|
||||||
END_API_CALLER_FUNC_void( (int, const void*), (p->i1, p->p1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(ushort, ip)
|
|
||||||
END_API_CALLER_FUNC( unsigned short, (int, const void*), (p->i1, p->p1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(int, ip)
|
|
||||||
END_API_CALLER_FUNC( int, (int, const void*), (p->i1, p->p1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, ipusf2p2f4i)
|
|
||||||
END_API_CALLER_FUNC_void( (int, const void*, unsigned short, float, const void*, const void*, float, float, int, int, int, int), (p->i1, p->p1, p->us1, p->f1, p->p2, p->p3, p->f2, p->f3, p->i2, p->i3, p->i4, p->i5) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, p)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*), (p->p1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(ptr, p)
|
|
||||||
END_API_CALLER_FUNC(void*, (const void*), (p->p1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(char, p)
|
|
||||||
END_API_CALLER_FUNC(char, (const void*), (p->p1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(int, p)
|
|
||||||
END_API_CALLER_FUNC(int, (const void*), (p->p1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(uint, p)
|
|
||||||
END_API_CALLER_FUNC(unsigned int, (const void*), (p->p1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(float, p)
|
|
||||||
END_API_CALLER_FUNC(float, (const void*), (p->p1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, p2f)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, float, float), (p->p1, p->f1, p->f2) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(int, p2fi)
|
|
||||||
END_API_CALLER_FUNC(int, (const void*, float, float, int), (p->p1, p->f1, p->f2, p->i1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, p2i)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, int, int), (p->p1, p->i1, p->i2) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, p3i)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, int, int, int), (p->p1, p->i1, p->i2, p->i3) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, p4i)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, int, int, int, int), (p->p1, p->i1, p->i2, p->i3, p->i4) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, puc)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, unsigned char), (p->p1, p->uc1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, pf)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, float), (p->p1, p->f1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, pfp)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, float, const void*), (p->p1, p->f1, p->p2) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, pi)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, int), (p->p1, p->i1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(ptr, pi)
|
|
||||||
END_API_CALLER_FUNC(void*, (const void*, int), (p->p1, p->i1) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(int, pi)
|
|
||||||
END_API_CALLER_FUNC(int, (const void*, int), (p->p1, p->i1) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, pi2p)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, int, const void*, const void*), (p->p1, p->i1, p->p2, p->p3) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(int, pi2p2ip)
|
|
||||||
END_API_CALLER_FUNC(int, (const void*, int, const void*, const void*, int, int, const void*), (p->p1, p->i1, p->p2, p->p3, p->i2, p->i3, p->p4) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, pip)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, int, const void*), (p->p1, p->i1, p->p2) );
|
|
||||||
|
|
||||||
BEGIN_API_CALLER_FUNC(ptr, pip)
|
|
||||||
END_API_CALLER_FUNC(void*, (const void*, int, const void*), (p->p1, p->i1, p->p2) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, pip2f2i)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, int, const void*, float, float, int, int), (p->p1, p->i1, p->p2, p->f1, p->f2, p->i2, p->i3) );
|
|
||||||
|
|
||||||
//-
|
|
||||||
BEGIN_API_CALLER_FUNC(void, pip2f4i2p)
|
|
||||||
END_API_CALLER_FUNC_void( (const void*, int, const void*, float, float, int, int, int, int, const void*, const void*), (p->p1, p->i1, p->p2, p->f1, p->f2, p->i2, p->i3, p->i4, p->i5, p->p3, p->p4) );
|
|
||||||
@@ -1,275 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// api_info.cpp - info for api routines
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "api_info.h" // me
|
|
||||||
#include "api_hook.h"
|
|
||||||
|
|
||||||
// trace flag, loglevel, name
|
|
||||||
const dllapi_info_t dllapi_info = {
|
|
||||||
{ mFALSE, 3, api_caller_void_args_void, "GameDLLInit" }, // pfnGameInit
|
|
||||||
{ mFALSE, 10, api_caller_int_args_p, "DispatchSpawn" }, // pfnSpawn
|
|
||||||
{ mFALSE, 16, api_caller_void_args_p, "DispatchThink" }, // pfnThink
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2p, "DispatchUse" }, // pfnUse
|
|
||||||
{ mFALSE, 11, api_caller_void_args_2p, "DispatchTouch" }, // pfnTouch
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2p, "DispatchBlocked" }, // pfnBlocked
|
|
||||||
{ mFALSE, 10, api_caller_void_args_2p, "DispatchKeyValue" }, // pfnKeyValue
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2p, "DispatchSave" }, // pfnSave
|
|
||||||
{ mFALSE, 9, api_caller_int_args_2pi, "DispatchRestore" }, // pfnRestore
|
|
||||||
{ mFALSE, 20, api_caller_void_args_p, "DispatchObjectCollsionBox" }, // pfnSetAbsBox
|
|
||||||
{ mFALSE, 9, api_caller_void_args_4pi, "SaveWriteFields" }, // pfnSaveWriteFields
|
|
||||||
{ mFALSE, 9, api_caller_void_args_4pi, "SaveReadFields" }, // pfnSaveReadFields
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "SaveGlobalState" }, // pfnSaveGlobalState
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "RestoreGlobalState" }, // pfnRestoreGlobalState
|
|
||||||
{ mFALSE, 9, api_caller_void_args_void, "ResetGlobalState" }, // pfnResetGlobalState
|
|
||||||
{ mFALSE, 3, api_caller_int_args_4p, "ClientConnect" }, // pfnClientConnect
|
|
||||||
{ mFALSE, 3, api_caller_void_args_p, "ClientDisconnect" }, // pfnClientDisconnect
|
|
||||||
{ mFALSE, 3, api_caller_void_args_p, "ClientKill" }, // pfnClientKill
|
|
||||||
{ mFALSE, 3, api_caller_void_args_p, "ClientPutInServer" }, // pfnClientPutInServer
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "ClientCommand" }, // pfnClientCommand
|
|
||||||
{ mFALSE, 11, api_caller_void_args_2p, "ClientUserInfoChanged" }, // pfnClientUserInfoChanged
|
|
||||||
{ mFALSE, 3, api_caller_void_args_p2i, "ServerActivate" }, // pfnServerActivate
|
|
||||||
{ mFALSE, 3, api_caller_void_args_void, "ServerDeactivate" }, // pfnServerDeactivate
|
|
||||||
{ mFALSE, 14, api_caller_void_args_p, "PlayerPreThink" }, // pfnPlayerPreThink
|
|
||||||
{ mFALSE, 14, api_caller_void_args_p, "PlayerPostThink" }, // pfnPlayerPostThink
|
|
||||||
{ mFALSE, 18, api_caller_void_args_void, "StartFrame" }, // pfnStartFrame
|
|
||||||
{ mFALSE, 9, api_caller_void_args_void, "ParmsNewLevel" }, // pfnParmsNewLevel
|
|
||||||
{ mFALSE, 9, api_caller_void_args_void, "ParmsChangeLevel" }, // pfnParmsChangeLevel
|
|
||||||
{ mFALSE, 9, api_caller_ptr_args_void, "GetGameDescription" }, // pfnGetGameDescription
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2p, "PlayerCustomization" }, // pfnPlayerCustomization
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "SpectatorConnect" }, // pfnSpectatorConnect
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "SpectatorDisconnect" }, // pfnSpectatorDisconnect
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "SpectatorThink" }, // pfnSpectatorThink
|
|
||||||
{ mFALSE, 3, api_caller_void_args_p, "Sys_Error" }, // pfnSys_Error
|
|
||||||
{ mFALSE, 13, api_caller_void_args_pi, "PM_Move" }, // pfnPM_Move
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "PM_Init" }, // pfnPM_Init
|
|
||||||
{ mFALSE, 9, api_caller_char_args_p, "PM_FindTextureType" }, // pfnPM_FindTextureType
|
|
||||||
{ mFALSE, 12, api_caller_void_args_4p, "SetupVisibility" }, // pfnSetupVisibility
|
|
||||||
{ mFALSE, 12, api_caller_void_args_pip, "UpdateClientData" }, // pfnUpdateClientData
|
|
||||||
{ mFALSE, 16, api_caller_int_args_pi2p2ip, "AddToFullPack" }, // pfnAddToFullPack
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2i2pi2p, "CreateBaseline" }, // pfnCreateBaseline
|
|
||||||
{ mFALSE, 9, api_caller_void_args_void, "RegisterEncoders" }, // pfnRegisterEncoders
|
|
||||||
{ mFALSE, 9, api_caller_int_args_2p, "GetWeaponData" }, // pfnGetWeaponData
|
|
||||||
{ mFALSE, 15, api_caller_void_args_2pui, "CmdStart" }, // pfnCmdStart
|
|
||||||
{ mFALSE, 15, api_caller_void_args_p, "CmdEnd" }, // pfnCmdEnd
|
|
||||||
{ mFALSE, 9, api_caller_int_args_4p, "ConnectionlessPacket" }, // pfnConnectionlessPacket
|
|
||||||
{ mFALSE, 9, api_caller_int_args_i2p, "GetHullBounds" }, // pfnGetHullBounds
|
|
||||||
{ mFALSE, 9, api_caller_void_args_void, "CreateInstancedBaselines" }, // pfnCreateInstancedBaselines
|
|
||||||
{ mFALSE, 3, api_caller_int_args_3p, "InconsistentFile" }, // pfnInconsistentFile
|
|
||||||
{ mFALSE, 20, api_caller_int_args_void, "AllowLagCompensation" }, // pfnAllowLagCompensation
|
|
||||||
{ mFALSE, 0, NULL, NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
const newapi_info_t newapi_info = {
|
|
||||||
{ mFALSE, 16, api_caller_void_args_p, "OnFreeEntPrivateData" }, // pfnOnFreeEntPrivateData
|
|
||||||
{ mFALSE, 3, api_caller_void_args_void, "GameShutdown" }, // pfnGameShutdown
|
|
||||||
{ mFALSE, 14, api_caller_int_args_2p, "ShouldCollide" }, // pfnShouldCollide
|
|
||||||
// Added 2005/08/11 (no SDK update):
|
|
||||||
{ mFALSE, 3, api_caller_void_args_2p, "CvarValue" }, // pfnCvarValue
|
|
||||||
// Added 2005/11/21 (no SDK update):
|
|
||||||
{ mFALSE, 3, api_caller_void_args_pi2p, "CvarValue2" }, // pfnCvarValue2
|
|
||||||
{ mFALSE, 0, NULL, NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
const engine_info_t engine_info = {
|
|
||||||
{ mFALSE, 13, api_caller_int_args_p, "PrecacheModel" }, // pfnPrecacheModel
|
|
||||||
{ mFALSE, 13, api_caller_int_args_p, "PrecacheSound" }, // pfnPrecacheSound
|
|
||||||
{ mFALSE, 18, api_caller_void_args_2p, "SetModel" }, // pfnSetModel
|
|
||||||
{ mFALSE, 34, api_caller_int_args_p, "ModelIndex" }, // pfnModelIndex
|
|
||||||
{ mFALSE, 10, api_caller_int_args_i, "ModelFrames" }, // pfnModelFrames
|
|
||||||
{ mFALSE, 14, api_caller_void_args_3p, "SetSize" }, // pfnSetSize
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2p, "ChangeLevel" }, // pfnChangeLevel
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "GetSpawnParms" }, // pfnGetSpawnParms
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "SaveSpawnParms" }, // pfnSaveSpawnParms
|
|
||||||
{ mFALSE, 9, api_caller_float_args_p, "VecToYaw" }, // pfnVecToYaw
|
|
||||||
{ mFALSE, 14, api_caller_void_args_2p, "VecToAngles" }, // pfnVecToAngles
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2pfi, "MoveToOrigin" }, // pfnMoveToOrigin
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "ChangeYaw" }, // pfnChangeYaw
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "ChangePitch" }, // pfnChangePitch
|
|
||||||
{ mFALSE, 32, api_caller_ptr_args_3p, "FindEntityByString" }, // pfnFindEntityByString
|
|
||||||
{ mFALSE, 9, api_caller_int_args_p, "GetEntityIllum" }, // pfnGetEntityIllum
|
|
||||||
{ mFALSE, 9, api_caller_ptr_args_2pf, "FindEntityInSphere" }, // pfnFindEntityInSphere
|
|
||||||
{ mFALSE, 19, api_caller_ptr_args_p, "FindClientInPVS" }, // pfnFindClientInPVS
|
|
||||||
{ mFALSE, 9, api_caller_ptr_args_p, "EntitiesInPVS" }, // pfnEntitiesInPVS
|
|
||||||
{ mFALSE, 40, api_caller_void_args_p, "MakeVectors" }, // pfnMakeVectors
|
|
||||||
{ mFALSE, 9, api_caller_void_args_4p, "AngleVectors" }, // pfnAngleVectors
|
|
||||||
{ mFALSE, 13, api_caller_ptr_args_void, "CreateEntity" }, // pfnCreateEntity
|
|
||||||
{ mFALSE, 13, api_caller_void_args_p, "RemoveEntity" }, // pfnRemoveEntity
|
|
||||||
{ mFALSE, 13, api_caller_ptr_args_i, "CreateNamedEntity" }, // pfnCreateNamedEntity
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "MakeStatic" }, // pfnMakeStatic
|
|
||||||
{ mFALSE, 9, api_caller_int_args_p, "EntIsOnFloor" }, // pfnEntIsOnFloor
|
|
||||||
{ mFALSE, 9, api_caller_int_args_p, "DropToFloor" }, // pfnDropToFloor
|
|
||||||
{ mFALSE, 9, api_caller_int_args_p2fi, "WalkMove" }, // pfnWalkMove
|
|
||||||
{ mFALSE, 14, api_caller_void_args_2p, "SetOrigin" }, // pfnSetOrigin
|
|
||||||
{ mFALSE, 12, api_caller_void_args_pip2f2i, "EmitSound" }, // pfnEmitSound
|
|
||||||
{ mFALSE, 12, api_caller_void_args_3p2f2i, "EmitAmbientSound" }, // pfnEmitAmbientSound
|
|
||||||
{ mFALSE, 20, api_caller_void_args_2pi2p, "TraceLine" }, // pfnTraceLine
|
|
||||||
{ mFALSE, 9, api_caller_void_args_3p, "TraceToss" }, // pfnTraceToss
|
|
||||||
{ mFALSE, 9, api_caller_int_args_3pi2p, "TraceMonsterHull" }, // pfnTraceMonsterHull
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2p2i2p, "TraceHull" }, // pfnTraceHull
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2pi2p, "TraceModel" }, // pfnTraceModel
|
|
||||||
{ mFALSE, 15, api_caller_ptr_args_3p, "TraceTexture" }, // pfnTraceTexture // CS: when moving
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2pif2p, "TraceSphere" }, // pfnTraceSphere
|
|
||||||
{ mFALSE, 9, api_caller_void_args_pfp, "GetAimVector" }, // pfnGetAimVector
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "ServerCommand" }, // pfnServerCommand
|
|
||||||
{ mFALSE, 9, api_caller_void_args_void, "ServerExecute" }, // pfnServerExecute
|
|
||||||
{ mFALSE, 11, api_caller_void_args_2pV, "engClientCommand" }, // pfnClientCommand // d'oh, ClientCommand in dllapi too
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2p2f, "ParticleEffect" }, // pfnParticleEffect
|
|
||||||
{ mFALSE, 9, api_caller_void_args_ip, "LightStyle" }, // pfnLightStyle
|
|
||||||
{ mFALSE, 9, api_caller_int_args_p, "DecalIndex" }, // pfnDecalIndex
|
|
||||||
{ mFALSE, 15, api_caller_int_args_p, "PointContents" }, // pfnPointContents // CS: when moving
|
|
||||||
{ mFALSE, 22, api_caller_void_args_2i2p, "MessageBegin" }, // pfnMessageBegin
|
|
||||||
{ mFALSE, 22, api_caller_void_args_void, "MessageEnd" }, // pfnMessageEnd
|
|
||||||
{ mFALSE, 30, api_caller_void_args_i, "WriteByte" }, // pfnWriteByte
|
|
||||||
{ mFALSE, 23, api_caller_void_args_i, "WriteChar" }, // pfnWriteChar
|
|
||||||
{ mFALSE, 24, api_caller_void_args_i, "WriteShort" }, // pfnWriteShort
|
|
||||||
{ mFALSE, 23, api_caller_void_args_i, "WriteLong" }, // pfnWriteLong
|
|
||||||
{ mFALSE, 23, api_caller_void_args_f, "WriteAngle" }, // pfnWriteAngle
|
|
||||||
{ mFALSE, 23, api_caller_void_args_f, "WriteCoord" }, // pfnWriteCoord
|
|
||||||
{ mFALSE, 25, api_caller_void_args_p, "WriteString" }, // pfnWriteString
|
|
||||||
{ mFALSE, 23, api_caller_void_args_i, "WriteEntity" }, // pfnWriteEntity
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "CVarRegister" }, // pfnCVarRegister
|
|
||||||
{ mFALSE, 21, api_caller_float_args_p, "CVarGetFloat" }, // pfnCVarGetFloat
|
|
||||||
{ mFALSE, 9, api_caller_ptr_args_p, "CVarGetString" }, // pfnCVarGetString
|
|
||||||
{ mFALSE, 10, api_caller_void_args_pf, "CVarSetFloat" }, // pfnCVarSetFloat
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2p, "CVarSetString" }, // pfnCVarSetString
|
|
||||||
{ mFALSE, 15, api_caller_void_args_ipV, "AlertMessage" }, // pfnAlertMessage
|
|
||||||
{ mFALSE, 17, api_caller_void_args_2pV, "EngineFprintf" }, // pfnEngineFprintf
|
|
||||||
{ mFALSE, 14, api_caller_ptr_args_pi, "PvAllocEntPrivateData" }, // pfnPvAllocEntPrivateData
|
|
||||||
{ mFALSE, 9, api_caller_ptr_args_p, "PvEntPrivateData" }, // pfnPvEntPrivateData
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "FreeEntPrivateData" }, // pfnFreeEntPrivateData
|
|
||||||
{ mFALSE, 9, api_caller_ptr_args_i, "SzFromIndex" }, // pfnSzFromIndex
|
|
||||||
{ mFALSE, 10, api_caller_int_args_p, "AllocString" }, // pfnAllocString
|
|
||||||
{ mFALSE, 9, api_caller_ptr_args_p, "GetVarsOfEnt" }, // pfnGetVarsOfEnt
|
|
||||||
{ mFALSE, 14, api_caller_ptr_args_i, "PEntityOfEntOffset" }, // pfnPEntityOfEntOffset
|
|
||||||
{ mFALSE, 19, api_caller_int_args_p, "EntOffsetOfPEntity" }, // pfnEntOffsetOfPEntity
|
|
||||||
{ mFALSE, 14, api_caller_int_args_p, "IndexOfEdict" }, // pfnIndexOfEdict
|
|
||||||
{ mFALSE, 17, api_caller_ptr_args_i, "PEntityOfEntIndex" }, // pfnPEntityOfEntIndex
|
|
||||||
{ mFALSE, 9, api_caller_ptr_args_p, "FindEntityByVars" }, // pfnFindEntityByVars
|
|
||||||
{ mFALSE, 14, api_caller_ptr_args_p, "GetModelPtr" }, // pfnGetModelPtr
|
|
||||||
{ mFALSE, 9, api_caller_int_args_pi, "RegUserMsg" }, // pfnRegUserMsg
|
|
||||||
{ mFALSE, 9, api_caller_void_args_pf, "AnimationAutomove" }, // pfnAnimationAutomove
|
|
||||||
{ mFALSE, 9, api_caller_void_args_pi2p, "GetBonePosition" }, // pfnGetBonePosition
|
|
||||||
{ mFALSE, 9, api_caller_uint_args_p, "FunctionFromName" }, // pfnFunctionFromName
|
|
||||||
{ mFALSE, 9, api_caller_ptr_args_ui, "NameForFunction" }, // pfnNameForFunction
|
|
||||||
{ mFALSE, 9, api_caller_void_args_pip, "ClientPrintf" }, // pfnClientPrintf
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "ServerPrint" }, // pfnServerPrint
|
|
||||||
{ mFALSE, 13, api_caller_ptr_args_void, "Cmd_Args" }, // pfnCmd_Args
|
|
||||||
{ mFALSE, 13, api_caller_ptr_args_i, "Cmd_Argv" }, // pfnCmd_Argv
|
|
||||||
{ mFALSE, 13, api_caller_int_args_void, "Cmd_Argc" }, // pfnCmd_Argc
|
|
||||||
{ mFALSE, 9, api_caller_void_args_pi2p, "GetAttachment" }, // pfnGetAttachment
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "CRC32_Init" }, // pfnCRC32_Init
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2pi, "CRC32_ProcessBuffer" }, // pfnCRC32_ProcessBuffer
|
|
||||||
{ mFALSE, 9, api_caller_void_args_puc, "CRC32_ProcessByte" }, // pfnCRC32_ProcessByte
|
|
||||||
{ mFALSE, 9, api_caller_ulong_args_ul, "CRC32_Final" }, // pfnCRC32_Final
|
|
||||||
{ mFALSE, 16, api_caller_int_args_2i, "RandomLong" }, // pfnRandomLong
|
|
||||||
{ mFALSE, 14, api_caller_float_args_2f, "RandomFloat" }, // pfnRandomFloat // CS: when firing
|
|
||||||
{ mFALSE, 14, api_caller_void_args_2p, "SetView" }, // pfnSetView
|
|
||||||
{ mFALSE, 9, api_caller_float_args_void, "Time" }, // pfnTime
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p2f, "CrosshairAngle" }, // pfnCrosshairAngle
|
|
||||||
{ mFALSE, 10, api_caller_ptr_args_2p, "LoadFileForMe" }, // pfnLoadFileForMe
|
|
||||||
{ mFALSE, 10, api_caller_void_args_p, "FreeFile" }, // pfnFreeFile
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "EndSection" }, // pfnEndSection
|
|
||||||
{ mFALSE, 9, api_caller_int_args_3p, "CompareFileTime" }, // pfnCompareFileTime
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "GetGameDir" }, // pfnGetGameDir
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p, "Cvar_RegisterVariable" }, // pfnCvar_RegisterVariable
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p4i, "FadeClientVolume" }, // pfnFadeClientVolume
|
|
||||||
{ mFALSE, 14, api_caller_void_args_pf, "SetClientMaxspeed" }, // pfnSetClientMaxspeed
|
|
||||||
{ mFALSE, 9, api_caller_ptr_args_p, "CreateFakeClient" }, // pfnCreateFakeClient
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2p3fus2uc, "RunPlayerMove" }, // pfnRunPlayerMove
|
|
||||||
{ mFALSE, 9, api_caller_int_args_void, "NumberOfEntities" }, // pfnNumberOfEntities
|
|
||||||
{ mFALSE, 17, api_caller_ptr_args_p, "GetInfoKeyBuffer" }, // pfnGetInfoKeyBuffer
|
|
||||||
{ mFALSE, 13, api_caller_ptr_args_2p, "InfoKeyValue" }, // pfnInfoKeyValue
|
|
||||||
{ mFALSE, 9, api_caller_void_args_3p, "SetKeyValue" }, // pfnSetKeyValue
|
|
||||||
{ mFALSE, 12, api_caller_void_args_i3p, "SetClientKeyValue" }, // pfnSetClientKeyValue
|
|
||||||
{ mFALSE, 9, api_caller_int_args_p, "IsMapValid" }, // pfnIsMapValid
|
|
||||||
{ mFALSE, 9, api_caller_void_args_p3i, "StaticDecal" }, // pfnStaticDecal
|
|
||||||
{ mFALSE, 9, api_caller_int_args_p, "PrecacheGeneric" }, // pfnPrecacheGeneric
|
|
||||||
{ mFALSE, 10, api_caller_int_args_p, "GetPlayerUserId" }, // pfnGetPlayerUserId
|
|
||||||
{ mFALSE, 9, api_caller_void_args_pip2f4i2p, "BuildSoundMsg" }, // pfnBuildSoundMsg
|
|
||||||
{ mFALSE, 9, api_caller_int_args_void, "IsDedicatedServer" }, // pfnIsDedicatedServer
|
|
||||||
{ mFALSE, 9, api_caller_ptr_args_p, "CVarGetPointer" }, // pfnCVarGetPointer
|
|
||||||
{ mFALSE, 9, api_caller_uint_args_p, "GetPlayerWONId" }, // pfnGetPlayerWONId
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2p, "Info_RemoveKey" }, // pfnInfo_RemoveKey
|
|
||||||
{ mFALSE, 15, api_caller_ptr_args_2p, "GetPhysicsKeyValue" }, // pfnGetPhysicsKeyValue
|
|
||||||
{ mFALSE, 14, api_caller_void_args_3p, "SetPhysicsKeyValue" }, // pfnSetPhysicsKeyValue
|
|
||||||
{ mFALSE, 15, api_caller_ptr_args_p, "GetPhysicsInfoString" }, // pfnGetPhysicsInfoString
|
|
||||||
{ mFALSE, 13, api_caller_ushort_args_ip, "PrecacheEvent" }, // pfnPrecacheEvent
|
|
||||||
{ mFALSE, 9, api_caller_void_args_ipusf2p2f4i,"PlaybackEvent" }, // pfnPlaybackEvent
|
|
||||||
{ mFALSE, 31, api_caller_ptr_args_p, "SetFatPVS" }, // pfnSetFatPVS
|
|
||||||
{ mFALSE, 31, api_caller_ptr_args_p, "SetFatPAS" }, // pfnSetFatPAS
|
|
||||||
{ mFALSE, 50, api_caller_int_args_2p, "CheckVisibility" }, // pfnCheckVisibility
|
|
||||||
{ mFALSE, 37, api_caller_void_args_2p, "DeltaSetField" }, // pfnDeltaSetField
|
|
||||||
{ mFALSE, 38, api_caller_void_args_2p, "DeltaUnsetField" }, // pfnDeltaUnsetField
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2p, "DeltaAddEncoder" }, // pfnDeltaAddEncoder
|
|
||||||
{ mFALSE, 45, api_caller_int_args_void, "GetCurrentPlayer" }, // pfnGetCurrentPlayer
|
|
||||||
{ mFALSE, 14, api_caller_int_args_p, "CanSkipPlayer" }, // pfnCanSkipPlayer
|
|
||||||
{ mFALSE, 9, api_caller_int_args_2p, "DeltaFindField" }, // pfnDeltaFindField
|
|
||||||
{ mFALSE, 37, api_caller_void_args_pi, "DeltaSetFieldByIndex" }, // pfnDeltaSetFieldByIndex
|
|
||||||
{ mFALSE, 38, api_caller_void_args_pi, "DeltaUnsetFieldByIndex" }, // pfnDeltaUnsetFieldByIndex
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2i, "SetGroupMask" }, // pfnSetGroupMask
|
|
||||||
{ mFALSE, 9, api_caller_int_args_ip, "engCreateInstancedBaseline" }, // pfnCreateInstancedBaseline // d'oh, CreateInstancedBaseline in dllapi too
|
|
||||||
{ mFALSE, 9, api_caller_void_args_2p, "Cvar_DirectSet" }, // pfnCvar_DirectSet
|
|
||||||
{ mFALSE, 9, api_caller_void_args_i3p, "ForceUnmodified" }, // pfnForceUnmodified
|
|
||||||
{ mFALSE, 9, api_caller_void_args_3p, "GetPlayerStats" }, // pfnGetPlayerStats
|
|
||||||
{ mFALSE, 3, api_caller_void_args_2p, "AddServerCommand" }, // pfnAddServerCommand
|
|
||||||
// Added in SDK 2.2:
|
|
||||||
{ mFALSE, 9, api_caller_int_args_2i, "Voice_GetClientListening" }, // Voice_GetClientListening
|
|
||||||
{ mFALSE, 9, api_caller_int_args_3i, "Voice_SetClientListening" }, // Voice_SetClientListening
|
|
||||||
// Added for HL 1109 (no SDK update):
|
|
||||||
{ mFALSE, 9, api_caller_ptr_args_p, "GetPlayerAuthId" }, // pfnGetPlayerAuthId
|
|
||||||
// Added 2003/11/10 (no SDK update):
|
|
||||||
{ mFALSE, 30, api_caller_ptr_args_2p, "SequenceGet" }, // pfnSequenceGet
|
|
||||||
{ mFALSE, 30, api_caller_ptr_args_pip, "SequencePickSentence" }, // pfnSequencePickSentence
|
|
||||||
{ mFALSE, 30, api_caller_int_args_p, "GetFileSize" }, // pfnGetFileSize
|
|
||||||
{ mFALSE, 30, api_caller_uint_args_p, "GetApproxWavePlayLen" }, // pfnGetApproxWavePlayLen
|
|
||||||
{ mFALSE, 30, api_caller_int_args_void, "IsCareerMatch" }, // pfnIsCareerMatch
|
|
||||||
{ mFALSE, 30, api_caller_int_args_p, "GetLocalizedStringLength" }, // pfnGetLocalizedStringLength
|
|
||||||
{ mFALSE, 30, api_caller_void_args_i, "RegisterTutorMessageShown" }, // pfnRegisterTutorMessageShown
|
|
||||||
{ mFALSE, 30, api_caller_int_args_i, "GetTimesTutorMessageShown" }, // pfnGetTimesTutorMessageShown
|
|
||||||
{ mFALSE, 30, api_caller_void_args_pi, "ProcessTutorMessageDecayBuffer" }, // pfnProcessTutorMessageDecayBuffer
|
|
||||||
{ mFALSE, 30, api_caller_void_args_pi, "ConstructTutorMessageDecayBuffer" }, // pfnConstructTutorMessageDecayBuffer
|
|
||||||
{ mFALSE, 9, api_caller_void_args_void, "ResetTutorMessageDecayData" }, // pfnResetTutorMessageDecayData
|
|
||||||
// Added 2005/08/11 (no SDK update):
|
|
||||||
{ mFALSE, 3, api_caller_void_args_2p, "QueryClientCvarValue" }, // pfnQueryClientCvarValue
|
|
||||||
// Added 2005/11/21 (no SDK update):
|
|
||||||
{ mFALSE, 3, api_caller_void_args_2pi, "QueryClientCvarValue2" }, // pfnQueryClientCvarValue2
|
|
||||||
// Added 2009-06-17 (no SDK update):
|
|
||||||
{ mFALSE, 8, api_caller_int_args_2p, "EngCheckParm" }, // pfnEngCheckParm
|
|
||||||
// end
|
|
||||||
{ mFALSE, 0, NULL, NULL },
|
|
||||||
};
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
make HOST=cygwin TARGET=win32 OPT=opt
|
|
||||||
make HOST=cygwin OPT=opt
|
|
||||||
make HOST=cygwin TARGET=amd64 OPT=opt
|
|
||||||
@@ -1,513 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// commands_meta.cpp - implementation of various console commands
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h> // strtol()
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "commands_meta.h" // me
|
|
||||||
#include "metamod.h" // Plugins, etc
|
|
||||||
#include "log_meta.h" // META_CONS, etc
|
|
||||||
#include "info_name.h" // VNAME, etc
|
|
||||||
#include "vdate.h" // COMPILE_TIME, COMPILE_TZONE
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef META_PERFMON
|
|
||||||
|
|
||||||
long double total_tsc=0;
|
|
||||||
unsigned long long count_tsc=0;
|
|
||||||
unsigned long long active_tsc=0;
|
|
||||||
unsigned long long min_tsc=0;
|
|
||||||
|
|
||||||
void DLLINTERNAL cmd_meta_tsc(void) {
|
|
||||||
if(!count_tsc)
|
|
||||||
return;
|
|
||||||
|
|
||||||
META_CONS(" ");
|
|
||||||
META_CONS(" count_tsc: %.0f", (double)count_tsc);
|
|
||||||
META_CONS(" mean_tsc: %.1f", (double)(total_tsc / count_tsc));
|
|
||||||
META_CONS(" min_tsc: %.0f", (double)min_tsc);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DLLINTERNAL cmd_meta_reset_tsc(void) {
|
|
||||||
total_tsc=0;
|
|
||||||
count_tsc=0;
|
|
||||||
min_tsc=0;
|
|
||||||
}
|
|
||||||
#endif /*META_PERFMON*/
|
|
||||||
|
|
||||||
// Register commands and cvars.
|
|
||||||
void DLLINTERNAL meta_register_cmdcvar() {
|
|
||||||
CVAR_REGISTER(&meta_debug);
|
|
||||||
CVAR_REGISTER(&meta_version);
|
|
||||||
|
|
||||||
meta_debug_value = (int)meta_debug.value;
|
|
||||||
|
|
||||||
REG_SVR_COMMAND("meta", svr_meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse "meta" console command.
|
|
||||||
void DLLHIDDEN svr_meta(void) {
|
|
||||||
const char *cmd;
|
|
||||||
cmd=CMD_ARGV(1);
|
|
||||||
// arguments: none
|
|
||||||
if(!strcasecmp(cmd, "version"))
|
|
||||||
cmd_meta_version();
|
|
||||||
else if(!strcasecmp(cmd, "gpl"))
|
|
||||||
cmd_meta_gpl();
|
|
||||||
else if(!strcasecmp(cmd, "refresh"))
|
|
||||||
cmd_meta_refresh();
|
|
||||||
else if(!strcasecmp(cmd, "list"))
|
|
||||||
cmd_meta_pluginlist();
|
|
||||||
else if(!strcasecmp(cmd, "cmds"))
|
|
||||||
cmd_meta_cmdlist();
|
|
||||||
else if(!strcasecmp(cmd, "cvars"))
|
|
||||||
cmd_meta_cvarlist();
|
|
||||||
else if(!strcasecmp(cmd, "game"))
|
|
||||||
cmd_meta_game();
|
|
||||||
else if(!strcasecmp(cmd, "config"))
|
|
||||||
cmd_meta_config();
|
|
||||||
// arguments: existing plugin(s)
|
|
||||||
else if(!strcasecmp(cmd, "pause"))
|
|
||||||
cmd_doplug(PC_PAUSE);
|
|
||||||
else if(!strcasecmp(cmd, "unpause"))
|
|
||||||
cmd_doplug(PC_UNPAUSE);
|
|
||||||
else if(!strcasecmp(cmd, "unload"))
|
|
||||||
cmd_doplug(PC_UNLOAD);
|
|
||||||
else if(!strcasecmp(cmd, "force_unload"))
|
|
||||||
cmd_doplug(PC_FORCE_UNLOAD);
|
|
||||||
else if(!strcasecmp(cmd, "reload"))
|
|
||||||
cmd_doplug(PC_RELOAD);
|
|
||||||
else if(!strcasecmp(cmd, "retry"))
|
|
||||||
cmd_doplug(PC_RETRY);
|
|
||||||
else if(!strcasecmp(cmd, "clear"))
|
|
||||||
cmd_doplug(PC_CLEAR);
|
|
||||||
else if(!strcasecmp(cmd, "info"))
|
|
||||||
cmd_doplug(PC_INFO);
|
|
||||||
else if(!strcasecmp(cmd, "require"))
|
|
||||||
cmd_doplug(PC_REQUIRE);
|
|
||||||
// arguments: filename, description
|
|
||||||
else if(!strcasecmp(cmd, "load"))
|
|
||||||
cmd_meta_load();
|
|
||||||
#ifdef META_PERFMON
|
|
||||||
else if(!strcasecmp(cmd, "tsc"))
|
|
||||||
cmd_meta_tsc();
|
|
||||||
else if(!strcasecmp(cmd, "reset_tsc"))
|
|
||||||
cmd_meta_reset_tsc();
|
|
||||||
#endif /*META_PERFMON*/
|
|
||||||
// unrecognized
|
|
||||||
else {
|
|
||||||
META_CONS("Unrecognized meta command: %s", cmd);
|
|
||||||
cmd_meta_usage();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse "meta" client command.
|
|
||||||
void DLLINTERNAL client_meta(edict_t *pEntity) {
|
|
||||||
const char *cmd;
|
|
||||||
cmd=CMD_ARGV(1);
|
|
||||||
META_LOG("ClientCommand 'meta %s' from player '%s'",
|
|
||||||
CMD_ARGS(), STRING(pEntity->v.netname));
|
|
||||||
// arguments: none
|
|
||||||
if(strmatch(cmd, "version"))
|
|
||||||
client_meta_version(pEntity);
|
|
||||||
else if(strmatch(cmd, "list"))
|
|
||||||
client_meta_pluginlist(pEntity);
|
|
||||||
else if(strmatch(cmd, "aybabtu"))
|
|
||||||
client_meta_aybabtu(pEntity);
|
|
||||||
// unrecognized
|
|
||||||
else {
|
|
||||||
META_CLIENT(pEntity, "Unrecognized meta command: %s", cmd);
|
|
||||||
client_meta_usage(pEntity);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print usage for "meta" console command.
|
|
||||||
void DLLINTERNAL cmd_meta_usage(void) {
|
|
||||||
META_CONS("usage: meta <command> [<arguments>]");
|
|
||||||
META_CONS("valid commands are:");
|
|
||||||
META_CONS(" version - display metamod version info");
|
|
||||||
META_CONS(" game - display gamedll info");
|
|
||||||
META_CONS(" list - list plugins currently loaded");
|
|
||||||
META_CONS(" cmds - list console cmds registered by plugins");
|
|
||||||
META_CONS(" cvars - list cvars registered by plugins");
|
|
||||||
META_CONS(" refresh - load/unload any new/deleted/updated plugins");
|
|
||||||
META_CONS(" config - show config info loaded from config.ini");
|
|
||||||
META_CONS(" load <name> - find and load a plugin with the given name");
|
|
||||||
META_CONS(" unload <plugin> - unload a loaded plugin");
|
|
||||||
META_CONS(" reload <plugin> - unload a plugin and load it again");
|
|
||||||
META_CONS(" info <plugin> - show all information about a plugin");
|
|
||||||
META_CONS(" pause <plugin> - pause a loaded, running plugin");
|
|
||||||
META_CONS(" unpause <plugin> - unpause a previously paused plugin");
|
|
||||||
META_CONS(" retry <plugin> - retry a plugin that previously failed its action");
|
|
||||||
META_CONS(" clear <plugin> - clear a failed plugin from the list");
|
|
||||||
META_CONS(" force_unload <plugin> - forcibly unload a loaded plugin");
|
|
||||||
META_CONS(" require <plugin> - exit server if plugin not loaded/running");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print usage for "meta" client command.
|
|
||||||
void DLLINTERNAL client_meta_usage(edict_t *pEntity) {
|
|
||||||
META_CLIENT(pEntity, "usage: meta <command> [<arguments>]");
|
|
||||||
META_CLIENT(pEntity, "valid commands are:");
|
|
||||||
META_CLIENT(pEntity, " version - display metamod version info");
|
|
||||||
META_CLIENT(pEntity, " list - list plugins currently loaded");
|
|
||||||
}
|
|
||||||
|
|
||||||
// "meta aybabtu" client command.
|
|
||||||
void DLLINTERNAL client_meta_aybabtu(edict_t *pEntity) {
|
|
||||||
META_CLIENT(pEntity, "%s", "All Your Base Are Belong To Us");
|
|
||||||
}
|
|
||||||
|
|
||||||
// "meta version" console command.
|
|
||||||
void DLLINTERNAL cmd_meta_version(void) {
|
|
||||||
if(CMD_ARGC() != 2) {
|
|
||||||
META_CONS("usage: meta version");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
META_CONS("%s v%s %s (%s)", VNAME, VVERSION, VDATE, META_INTERFACE_VERSION);
|
|
||||||
META_CONS("by %s", VAUTHOR);
|
|
||||||
META_CONS(" %s", VURL);
|
|
||||||
META_CONS(" Patch: %s v%d", VPATCH_NAME, VPATCH_IVERSION);
|
|
||||||
META_CONS(" by %s", VPATCH_AUTHOR);
|
|
||||||
META_CONS(" %s", VPATCH_WEBSITE);
|
|
||||||
META_CONS("compiled: %s %s (%s)", COMPILE_TIME, COMPILE_TZONE, OPT_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// "meta version" client command.
|
|
||||||
void DLLINTERNAL client_meta_version(edict_t *pEntity) {
|
|
||||||
if(CMD_ARGC() != 2) {
|
|
||||||
META_CLIENT(pEntity, "usage: meta version");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
META_CLIENT(pEntity, "%s v%s %s (%s)", VNAME, VVERSION, VDATE, META_INTERFACE_VERSION);
|
|
||||||
META_CLIENT(pEntity, "by %s", VAUTHOR);
|
|
||||||
META_CLIENT(pEntity, " %s", VURL);
|
|
||||||
META_CLIENT(pEntity, " Patch: %s v%d", VPATCH_NAME, VPATCH_IVERSION);
|
|
||||||
META_CLIENT(pEntity, " by %s", VPATCH_AUTHOR);
|
|
||||||
META_CLIENT(pEntity, " %s", VPATCH_WEBSITE);
|
|
||||||
META_CLIENT(pEntity, "compiled: %s %s (%s)", COMPILE_TIME, COMPILE_TZONE, OPT_TYPE);
|
|
||||||
META_CLIENT(pEntity, "ifvers: %s", META_INTERFACE_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
// "meta gpl" console command.
|
|
||||||
void DLLINTERNAL cmd_meta_gpl(void) {
|
|
||||||
META_CONS("%s version %s %s", VNAME, VVERSION, VDATE);
|
|
||||||
META_CONS("Copyright (c) 2001-%s %s", COPYRIGHT_YEAR, VAUTHOR);
|
|
||||||
META_CONS("");
|
|
||||||
META_CONS(" %s is free software; you can redistribute it and/or", VNAME);
|
|
||||||
META_CONS(" modify it under the terms of the GNU General Public License");
|
|
||||||
META_CONS(" as published by the Free Software Foundation; either");
|
|
||||||
META_CONS(" version 2 of the License, or (at your option) any later");
|
|
||||||
META_CONS(" version.");
|
|
||||||
META_CONS(" ");
|
|
||||||
META_CONS(" %s is distributed in the hope that it will be useful,", VNAME);
|
|
||||||
META_CONS(" but WITHOUT ANY WARRANTY; without even the implied warranty");
|
|
||||||
META_CONS(" of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
|
|
||||||
META_CONS(" See the GNU General Public License for more details.");
|
|
||||||
META_CONS(" ");
|
|
||||||
META_CONS(" You should have received a copy of the GNU General Public");
|
|
||||||
META_CONS(" License along with Metamod; if not, write to the Free");
|
|
||||||
META_CONS(" Software Foundation, Inc., 59 Temple Place, Suite 330,");
|
|
||||||
META_CONS(" Boston, MA 02111-1307 USA");
|
|
||||||
META_CONS(" ");
|
|
||||||
META_CONS(" In addition, as a special exception, the author gives");
|
|
||||||
META_CONS(" permission to link the code of this program with the");
|
|
||||||
META_CONS(" Half-Life Game Engine (\"HL Engine\") and Modified Game");
|
|
||||||
META_CONS(" Libraries (\"MODs\") developed by Valve, L.L.C (\"Valve\").");
|
|
||||||
META_CONS(" You must obey the GNU General Public License in all");
|
|
||||||
META_CONS(" respects for all of the code used other than the HL Engine");
|
|
||||||
META_CONS(" and MODs from Valve. If you modify this file, you may");
|
|
||||||
META_CONS(" extend this exception to your version of the file, but you");
|
|
||||||
META_CONS(" are not obligated to do so. If you do not wish to do so,");
|
|
||||||
META_CONS(" delete this exception statement from your version.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// "meta game" console command.
|
|
||||||
void DLLINTERNAL cmd_meta_game(void) {
|
|
||||||
if(CMD_ARGC() != 2) {
|
|
||||||
META_CONS("usage: meta game");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
META_CONS("GameDLL info:");
|
|
||||||
META_CONS(" name: %s", GameDLL.name);
|
|
||||||
META_CONS(" desc: %s", GameDLL.desc);
|
|
||||||
META_CONS(" gamedir: %s", GameDLL.gamedir);
|
|
||||||
META_CONS(" dll file: %s", GameDLL.file);
|
|
||||||
META_CONS("dll pathname: %s", GameDLL.pathname);
|
|
||||||
RegMsgs->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
// "meta refresh" console command.
|
|
||||||
void DLLINTERNAL cmd_meta_refresh(void) {
|
|
||||||
if(CMD_ARGC() != 2) {
|
|
||||||
META_CONS("usage: meta refresh");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
META_LOG("Refreshing the plugins on demand...");
|
|
||||||
if(Plugins->refresh(PT_ANYTIME) != mTRUE) {
|
|
||||||
META_LOG("Refresh failed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// "meta list" console command.
|
|
||||||
void DLLINTERNAL cmd_meta_pluginlist(void) {
|
|
||||||
if(CMD_ARGC() != 2) {
|
|
||||||
META_CONS("usage: meta list");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Plugins->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
// "meta list" client command.
|
|
||||||
void DLLINTERNAL client_meta_pluginlist(edict_t *pEntity) {
|
|
||||||
if(CMD_ARGC() != 2) {
|
|
||||||
META_CLIENT(pEntity, "usage: meta list");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Plugins->show_client(pEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
// "meta cmds" console command.
|
|
||||||
void DLLINTERNAL cmd_meta_cmdlist(void) {
|
|
||||||
if(CMD_ARGC() != 2) {
|
|
||||||
META_CONS("usage: meta cmds");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RegCmds->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
// "meta cvars" console command.
|
|
||||||
void DLLINTERNAL cmd_meta_cvarlist(void) {
|
|
||||||
if(CMD_ARGC() != 2) {
|
|
||||||
META_CONS("usage: meta cvars");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RegCvars->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
// "meta config" console command.
|
|
||||||
void DLLINTERNAL cmd_meta_config(void) {
|
|
||||||
if(CMD_ARGC() != 2) {
|
|
||||||
META_CONS("usage: meta cvars");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Config->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
// gamedir/filename
|
|
||||||
// gamedir/dlls/filename
|
|
||||||
//
|
|
||||||
// dir/mm_file
|
|
||||||
// dir/file
|
|
||||||
//
|
|
||||||
// path
|
|
||||||
// path_mm
|
|
||||||
// path_MM
|
|
||||||
// path.so, path.dll
|
|
||||||
// path_i386.so, path_i486.so, etc
|
|
||||||
|
|
||||||
// "meta load" console command.
|
|
||||||
void DLLINTERNAL cmd_meta_load(void) {
|
|
||||||
int argc;
|
|
||||||
const char *args;
|
|
||||||
argc=CMD_ARGC();
|
|
||||||
if(argc < 3) {
|
|
||||||
META_CONS("usage: meta load <name> [<description>]");
|
|
||||||
META_CONS(" where <name> is an identifier used to locate the plugin file.");
|
|
||||||
META_CONS(" The system will look for a number of files based on this name, including:");
|
|
||||||
META_CONS(" name");
|
|
||||||
#ifdef linux
|
|
||||||
META_CONS(" name.so");
|
|
||||||
META_CONS(" name_mm.so");
|
|
||||||
META_CONS(" name_MM.so");
|
|
||||||
META_CONS(" mm_name.so");
|
|
||||||
#ifdef __x86_64__
|
|
||||||
META_CONS(" name_amd64.so");
|
|
||||||
META_CONS(" name_x86_64.so");
|
|
||||||
#else
|
|
||||||
META_CONS(" name_i386.so");
|
|
||||||
META_CONS(" name_i686.so");
|
|
||||||
#endif
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
META_CONS(" name.dll");
|
|
||||||
META_CONS(" name_mm.dll");
|
|
||||||
META_CONS(" mm_name.dll");
|
|
||||||
#endif /* linux */
|
|
||||||
META_CONS(" in a number of directories, including:");
|
|
||||||
META_CONS(" <gamedir>");
|
|
||||||
META_CONS(" <gamedir>/dlls");
|
|
||||||
META_CONS(" <given path, if absolute>");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
args=CMD_ARGS();
|
|
||||||
// cmd_addload() handles all the feedback to the console..
|
|
||||||
Plugins->cmd_addload(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle various console commands that refer to a known/loaded plugin.
|
|
||||||
void DLLINTERNAL cmd_doplug(PLUG_CMD pcmd) {
|
|
||||||
int i=0, argc;
|
|
||||||
const char *cmd, *arg;
|
|
||||||
MPlugin *findp;
|
|
||||||
|
|
||||||
argc=CMD_ARGC();
|
|
||||||
cmd=CMD_ARGV(1);
|
|
||||||
if(argc < 3) {
|
|
||||||
META_CONS("usage: meta %s <plugin> [<plugin> ...]", cmd);
|
|
||||||
META_CONS(" where <plugin> can be either the plugin index #");
|
|
||||||
META_CONS(" or a non-ambiguous prefix string matching name, desc, file, or logtag");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// i=2 to skip first arg, as that's the "cmd"
|
|
||||||
for(i=2; i < argc; i++) {
|
|
||||||
int pindex;
|
|
||||||
char *endptr;
|
|
||||||
|
|
||||||
arg=CMD_ARGV(i);
|
|
||||||
|
|
||||||
// try to match plugin id first
|
|
||||||
pindex = strtol(arg, &endptr, 10);
|
|
||||||
if(*arg && !*endptr)
|
|
||||||
findp=Plugins->find(pindex);
|
|
||||||
// else try to match some string (prefix)
|
|
||||||
else
|
|
||||||
findp=Plugins->find_match(arg);
|
|
||||||
|
|
||||||
// Require that:
|
|
||||||
// - specified plugin was found in the list of current plugins
|
|
||||||
// - plugin successfully loaded and began running
|
|
||||||
// Otherwise, print error and exit.
|
|
||||||
if(pcmd==PC_REQUIRE) {
|
|
||||||
if(findp && findp->status >= PL_RUNNING) {
|
|
||||||
META_DEBUG(3, ("Required plugin '%s' found loaded and running.",
|
|
||||||
arg));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Output to both places, because we don't want the admin
|
|
||||||
// to miss this..
|
|
||||||
if(!findp && meta_errno == ME_NOTUNIQ) {
|
|
||||||
META_ERROR("Unique match for required plugin '%s' was not found! Exiting.", arg);
|
|
||||||
META_CONS("\nERROR: Unique match for required plugin '%s' was not found! Exiting.\n", arg);
|
|
||||||
}
|
|
||||||
else if(!findp) {
|
|
||||||
META_ERROR("Required plugin '%s' was not found! Exiting.",
|
|
||||||
arg);
|
|
||||||
META_CONS("\nERROR: Required plugin '%s' was not found! Exiting.\n",
|
|
||||||
arg);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
META_ERROR("Required plugin '%s' did not load successfully! (status=%s) Exiting.", arg, findp->str_status(ST_SIMPLE));
|
|
||||||
META_CONS("\nERROR: Required plugin '%s' did not load successfully! (status=%s) Exiting.\n", arg, findp->str_status(ST_SIMPLE));
|
|
||||||
}
|
|
||||||
// Allow chance to read the message, before any window closes.
|
|
||||||
do_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!findp) {
|
|
||||||
if(meta_errno == ME_NOTUNIQ)
|
|
||||||
META_CONS("Couldn't find unique plugin matching '%s'", arg);
|
|
||||||
else
|
|
||||||
META_CONS("Couldn't find plugin matching '%s'", arg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pcmd==PC_PAUSE) {
|
|
||||||
if(findp->pause())
|
|
||||||
META_CONS("Paused plugin '%s'", findp->desc);
|
|
||||||
else
|
|
||||||
META_CONS("Pause failed for plugin '%s'", findp->desc);
|
|
||||||
}
|
|
||||||
else if(pcmd==PC_UNPAUSE) {
|
|
||||||
if(findp->unpause())
|
|
||||||
META_CONS("Unpaused plugin '%s'", findp->desc);
|
|
||||||
else
|
|
||||||
META_CONS("Unpause failed for plugin '%s'", findp->desc);
|
|
||||||
}
|
|
||||||
else if(pcmd==PC_UNLOAD) {
|
|
||||||
findp->action=PA_UNLOAD;
|
|
||||||
if(findp->unload(PT_ANYTIME, PNL_COMMAND, PNL_COMMAND)) {
|
|
||||||
META_CONS("Unloaded plugin '%s'", findp->desc);
|
|
||||||
Plugins->show();
|
|
||||||
}
|
|
||||||
else if(meta_errno == ME_DELAYED)
|
|
||||||
META_CONS("Unload delayed for plugin '%s'", findp->desc);
|
|
||||||
else
|
|
||||||
META_CONS("Unload failed for plugin '%s'", findp->desc);
|
|
||||||
}
|
|
||||||
else if(pcmd==PC_FORCE_UNLOAD) {
|
|
||||||
findp->action=PA_UNLOAD;
|
|
||||||
if(findp->unload(PT_ANYTIME, PNL_CMD_FORCED, PNL_CMD_FORCED)) {
|
|
||||||
META_CONS("Forced unload plugin '%s'", findp->desc);
|
|
||||||
Plugins->show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
META_CONS("Forced unload failed for plugin '%s'", findp->desc);
|
|
||||||
}
|
|
||||||
else if(pcmd==PC_RELOAD) {
|
|
||||||
findp->action=PA_RELOAD;
|
|
||||||
if(findp->reload(PT_ANYTIME, PNL_COMMAND))
|
|
||||||
META_CONS("Reloaded plugin '%s'", findp->desc);
|
|
||||||
else if(meta_errno == ME_DELAYED)
|
|
||||||
META_CONS("Reload delayed for plugin '%s'", findp->desc);
|
|
||||||
else if(meta_errno == ME_NOTALLOWED)
|
|
||||||
META_CONS("Reload not allowed for plugin '%s' now, only allowed %s", findp->desc, findp->str_loadable(SL_ALLOWED));
|
|
||||||
else
|
|
||||||
META_CONS("Reload failed for plugin '%s'", findp->desc);
|
|
||||||
}
|
|
||||||
else if(pcmd==PC_RETRY) {
|
|
||||||
if(findp->retry(PT_ANYTIME, PNL_COMMAND))
|
|
||||||
META_CONS("Retry succeeded for plugin '%s'", findp->desc);
|
|
||||||
else
|
|
||||||
META_CONS("Retry failed for plugin '%s'", findp->desc);
|
|
||||||
}
|
|
||||||
else if(pcmd==PC_CLEAR) {
|
|
||||||
if(findp->clear()) {
|
|
||||||
META_CONS("Cleared failed plugin '%s' from list", findp->desc);
|
|
||||||
Plugins->show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
META_CONS("Clear failed for plugin '%s'", findp->desc);
|
|
||||||
}
|
|
||||||
else if(pcmd==PC_INFO)
|
|
||||||
findp->show();
|
|
||||||
else {
|
|
||||||
META_WARNING("Unexpected plug_cmd: %d", pcmd);
|
|
||||||
META_CONS("Command failed; see log");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,240 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// conf_meta.cpp - configfile reading routines
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h> // FILE,
|
|
||||||
#include <stdlib.h> // atoi
|
|
||||||
#include <ctype.h> // isdigit
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "conf_meta.h" // me
|
|
||||||
#include "support_meta.h" // strmatch
|
|
||||||
#include "osdep.h" // strtok,
|
|
||||||
|
|
||||||
MConfig::MConfig(void)
|
|
||||||
: list(NULL), filename(NULL), debuglevel(0), gamedll(NULL),
|
|
||||||
plugins_file(NULL), exec_cfg(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize default values from the stored options struct. Has to happen
|
|
||||||
// _after_ constructor, so that all the fields are allocated (d'oh).
|
|
||||||
void DLLINTERNAL MConfig::init(option_t *global_options) {
|
|
||||||
option_t *optp;
|
|
||||||
list=global_options;
|
|
||||||
for(optp=list; optp->name; optp++)
|
|
||||||
set(optp, optp->init);
|
|
||||||
}
|
|
||||||
|
|
||||||
option_t * DLLINTERNAL MConfig::find(const char *lookup) {
|
|
||||||
option_t *optp;
|
|
||||||
|
|
||||||
for(optp=list; optp->name && !strmatch(optp->name, lookup); optp++);
|
|
||||||
if(optp->name)
|
|
||||||
return(optp);
|
|
||||||
else
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
mBOOL DLLINTERNAL MConfig::set(const char *key, const char *value) {
|
|
||||||
option_t *optp;
|
|
||||||
optp=find(key);
|
|
||||||
if(optp)
|
|
||||||
return(set(optp, value));
|
|
||||||
else
|
|
||||||
RETURN_ERRNO(mFALSE, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
mBOOL DLLINTERNAL MConfig::set(option_t *setp, const char *setstr) {
|
|
||||||
char pathbuf[PATH_MAX];
|
|
||||||
int *optval = (int *) setp->dest;
|
|
||||||
char **optstr = (char **) setp->dest;
|
|
||||||
// cvar_t *optcvar = (cvar_t *) setp->dest;
|
|
||||||
// SETOPT_FN optcmd = (SETOPT_FN) setp->dest;
|
|
||||||
|
|
||||||
if(!setstr)
|
|
||||||
return(mTRUE);
|
|
||||||
|
|
||||||
switch(setp->type) {
|
|
||||||
case CF_INT:
|
|
||||||
if(!isdigit(setstr[0])) {
|
|
||||||
META_WARNING("option '%s' invalid format '%s'", setp->name, setstr);
|
|
||||||
RETURN_ERRNO(mFALSE, ME_FORMAT);
|
|
||||||
}
|
|
||||||
*optval=atoi(setstr);
|
|
||||||
META_DEBUG(3, ("set config int: %s = %d", setp->name, *optval));
|
|
||||||
break;
|
|
||||||
case CF_BOOL:
|
|
||||||
if(strcasematch(setstr, "true")
|
|
||||||
|| strcasematch(setstr, "yes")
|
|
||||||
|| strmatch(setstr, "1"))
|
|
||||||
{
|
|
||||||
*optval=1;
|
|
||||||
}
|
|
||||||
else if(strcasematch(setstr, "false")
|
|
||||||
|| strcasematch(setstr, "no")
|
|
||||||
|| strmatch(setstr, "0"))
|
|
||||||
{
|
|
||||||
*optval=0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
META_WARNING("option '%s' invalid format '%s'", setp->name, setstr);
|
|
||||||
RETURN_ERRNO(mFALSE, ME_FORMAT);
|
|
||||||
}
|
|
||||||
META_DEBUG(3, ("set config bool: %s = %s", setp->name, *optval ? "true" : "false"));
|
|
||||||
break;
|
|
||||||
case CF_STR:
|
|
||||||
if(*optstr)
|
|
||||||
free(*optstr);
|
|
||||||
*optstr=strdup(setstr);
|
|
||||||
META_DEBUG(3, ("set config string: %s = %s", setp->name, *optstr));
|
|
||||||
break;
|
|
||||||
case CF_PATH:
|
|
||||||
if(*optstr)
|
|
||||||
free(*optstr);
|
|
||||||
full_gamedir_path(setstr, pathbuf);
|
|
||||||
*optstr=strdup(pathbuf);
|
|
||||||
META_DEBUG(3, ("set config path: %s = %s", setp->name, *optstr));
|
|
||||||
break;
|
|
||||||
#if 0
|
|
||||||
case CF_CVAR:
|
|
||||||
CVAR_SET_STRING(optcvar->name, setstr);
|
|
||||||
META_DEBUG(3, ("set config cvar: %s = %s", optcvar->name, setstr));
|
|
||||||
break;
|
|
||||||
case CF_CMD:
|
|
||||||
optcmd(setp->name, setstr);
|
|
||||||
META_DEBUG(3, ("set config command: %s, %s", optcvar->name, setstr));
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
META_WARNING("unrecognized config type '%d'", setp->type);
|
|
||||||
RETURN_ERRNO(mFALSE, ME_ARGUMENT);
|
|
||||||
}
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
mBOOL DLLINTERNAL MConfig::load(const char *fn) {
|
|
||||||
FILE *fp;
|
|
||||||
char loadfile[PATH_MAX];
|
|
||||||
char line[MAX_CONF_LEN];
|
|
||||||
char *optname, *optval;
|
|
||||||
option_t *optp;
|
|
||||||
int ln;
|
|
||||||
|
|
||||||
// Make full pathname (from gamedir if relative, collapse "..",
|
|
||||||
// backslashes, etc).
|
|
||||||
full_gamedir_path(fn, loadfile);
|
|
||||||
|
|
||||||
fp=fopen(loadfile, "r");
|
|
||||||
if(!fp) {
|
|
||||||
META_WARNING("unable to open config file '%s': %s", loadfile,
|
|
||||||
strerror(errno));
|
|
||||||
RETURN_ERRNO(mFALSE, ME_NOFILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
META_DEBUG(2, ("Loading from config file: %s", loadfile));
|
|
||||||
for(ln=1; !feof(fp) && fgets(line, sizeof(line), fp); ln++) {
|
|
||||||
if(line[0]=='#')
|
|
||||||
continue;
|
|
||||||
if(line[0]==';')
|
|
||||||
continue;
|
|
||||||
if(strnmatch(line, "//", 2))
|
|
||||||
continue;
|
|
||||||
if(!(optname=strtok(line, " \t\r\n"))) {
|
|
||||||
META_WARNING("'%s' line %d: bad config format: missing option",
|
|
||||||
loadfile, ln);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(!(optval=strtok(NULL, "\r\n"))) {
|
|
||||||
META_WARNING("'%s' line %d: bad config format: missing value",
|
|
||||||
loadfile, ln);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(optp=find(optname))) {
|
|
||||||
META_WARNING("'%s' line %d: unknown option name '%s'",
|
|
||||||
loadfile, ln, optname);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!set(optp, optval)) {
|
|
||||||
META_WARNING("'%s' line %d: unable to set option '%s' value '%s'",
|
|
||||||
loadfile, ln, optname, optval);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
filename=strdup(loadfile);
|
|
||||||
fclose(fp);
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DLLINTERNAL MConfig::show(void) {
|
|
||||||
option_t *optp;
|
|
||||||
if(filename)
|
|
||||||
META_CONS("%s and %s:", "Config options from localinfo", filename);
|
|
||||||
else
|
|
||||||
META_CONS("%s:", "Config options from localinfo");
|
|
||||||
for(optp=list; optp->name; optp++) {
|
|
||||||
int *optval = (int *) optp->dest;
|
|
||||||
char **optstr = (char **) optp->dest;
|
|
||||||
// cvar_t *optcvar = (cvar_t *) optp->dest;
|
|
||||||
// SETOPT_FN optcmd = (SETOPT_FN) optp->dest;
|
|
||||||
switch(optp->type) {
|
|
||||||
case CF_INT:
|
|
||||||
META_CONS(" %-20s\t%d\n", optp->name, *optval);
|
|
||||||
break;
|
|
||||||
case CF_BOOL:
|
|
||||||
META_CONS(" %-20s\t%s\n", optp->name,
|
|
||||||
*optval ? "true" : "false");
|
|
||||||
break;
|
|
||||||
case CF_STR:
|
|
||||||
case CF_PATH:
|
|
||||||
META_CONS(" %-20s\t%s\n", optp->name,
|
|
||||||
*optstr ? *optstr : "");
|
|
||||||
break;
|
|
||||||
#if 0
|
|
||||||
case CF_CVAR:
|
|
||||||
META_CONS(" %-20s\tstores in: %s\n", optp->name, optcvar->name);
|
|
||||||
break;
|
|
||||||
case CF_CMD:
|
|
||||||
META_CONS(" %-20s\tparsed by: %d\n", optp->name, (int) optcmd);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
case CF_NONE:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,513 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// dllapi.cpp - implementation of Half-Life DLL routines
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stddef.h> // offsetof
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "dllapi.h" // me
|
|
||||||
#include "metamod.h" // SETUP_API_CALLS, etc
|
|
||||||
#include "api_info.h" // dllapi_info, etc
|
|
||||||
#include "commands_meta.h" // client_meta, etc
|
|
||||||
#include "log_meta.h" // META_ERROR, etc
|
|
||||||
#include "api_hook.h"
|
|
||||||
|
|
||||||
|
|
||||||
// Original DLL routines, functions returning "void".
|
|
||||||
#define META_DLLAPI_HANDLE_void(FN_TYPE, pfnName, pack_args_type, pfn_args) \
|
|
||||||
API_START_TSC_TRACKING(); \
|
|
||||||
API_PACK_ARGS(pack_args_type, pfn_args); \
|
|
||||||
main_hook_function_void(offsetof(dllapi_info_t, pfnName), e_api_dllapi, offsetof(DLL_FUNCTIONS, pfnName), &packed_args); \
|
|
||||||
API_END_TSC_TRACKING()
|
|
||||||
|
|
||||||
// Original DLL routines, functions returning an actual value.
|
|
||||||
#define META_DLLAPI_HANDLE(ret_t, ret_init, FN_TYPE, pfnName, pack_args_type, pfn_args) \
|
|
||||||
API_START_TSC_TRACKING(); \
|
|
||||||
API_PACK_ARGS(pack_args_type, pfn_args); \
|
|
||||||
class_ret_t ret_val(main_hook_function(class_ret_t((ret_t)ret_init), offsetof(dllapi_info_t, pfnName), e_api_dllapi, offsetof(DLL_FUNCTIONS, pfnName), &packed_args)); \
|
|
||||||
API_END_TSC_TRACKING()
|
|
||||||
|
|
||||||
// The "new" api routines (just 3 right now), functions returning "void".
|
|
||||||
#define META_NEWAPI_HANDLE_void(FN_TYPE, pfnName, pack_args_type, pfn_args) \
|
|
||||||
API_START_TSC_TRACKING(); \
|
|
||||||
API_PACK_ARGS(pack_args_type, pfn_args); \
|
|
||||||
main_hook_function_void(offsetof(newapi_info_t, pfnName), e_api_newapi, offsetof(NEW_DLL_FUNCTIONS, pfnName), &packed_args); \
|
|
||||||
API_END_TSC_TRACKING()
|
|
||||||
|
|
||||||
// The "new" api routines (just 3 right now), functions returning an actual value.
|
|
||||||
#define META_NEWAPI_HANDLE(ret_t, ret_init, FN_TYPE, pfnName, pack_args_type, pfn_args) \
|
|
||||||
API_START_TSC_TRACKING(); \
|
|
||||||
API_PACK_ARGS(pack_args_type, pfn_args); \
|
|
||||||
class_ret_t ret_val(main_hook_function(class_ret_t((ret_t)ret_init), offsetof(newapi_info_t, pfnName), e_api_newapi, offsetof(NEW_DLL_FUNCTIONS, pfnName), &packed_args)); \
|
|
||||||
API_END_TSC_TRACKING()
|
|
||||||
|
|
||||||
|
|
||||||
// From SDK dlls/game.cpp:
|
|
||||||
static void mm_GameDLLInit(void) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_GAMEINIT, pfnGameInit, void, (VOID_ARG));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
|
|
||||||
// From SDK dlls/cbase.cpp:
|
|
||||||
static int mm_DispatchSpawn(edict_t *pent) {
|
|
||||||
// 0==Success, -1==Failure ?
|
|
||||||
META_DLLAPI_HANDLE(int, 0, FN_DISPATCHSPAWN, pfnSpawn, p, (pent));
|
|
||||||
RETURN_API(int);
|
|
||||||
}
|
|
||||||
static void mm_DispatchThink(edict_t *pent) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_DISPATCHTHINK, pfnThink, p, (pent));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_DispatchUse(edict_t *pentUsed, edict_t *pentOther) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_DISPATCHUSE, pfnUse, 2p, (pentUsed, pentOther));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_DispatchTouch(edict_t *pentTouched, edict_t *pentOther) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_DISPATCHTOUCH, pfnTouch, 2p, (pentTouched, pentOther));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_DispatchBlocked(edict_t *pentBlocked, edict_t *pentOther) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_DISPATCHBLOCKED, pfnBlocked, 2p, (pentBlocked, pentOther));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_DispatchKeyValue(edict_t *pentKeyvalue, KeyValueData *pkvd) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_DISPATCHKEYVALUE, pfnKeyValue, 2p, (pentKeyvalue, pkvd));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_DispatchSave(edict_t *pent, SAVERESTOREDATA *pSaveData) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_DISPATCHSAVE, pfnSave, 2p, (pent, pSaveData));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static int mm_DispatchRestore(edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity) {
|
|
||||||
// 0==Success, -1==Failure ?
|
|
||||||
META_DLLAPI_HANDLE(int, 0, FN_DISPATCHRESTORE, pfnRestore, 2pi, (pent, pSaveData, globalEntity));
|
|
||||||
RETURN_API(int);
|
|
||||||
}
|
|
||||||
static void mm_DispatchObjectCollsionBox(edict_t *pent) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_DISPATCHOBJECTCOLLISIONBOX, pfnSetAbsBox, p, (pent));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_SaveWriteFields(SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_SAVEWRITEFIELDS, pfnSaveWriteFields, 4pi, (pSaveData, pname, pBaseData, pFields, fieldCount));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_SaveReadFields(SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_SAVEREADFIELDS, pfnSaveReadFields, 4pi, (pSaveData, pname, pBaseData, pFields, fieldCount));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
|
|
||||||
// From SDK dlls/world.cpp:
|
|
||||||
static void mm_SaveGlobalState(SAVERESTOREDATA *pSaveData) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_SAVEGLOBALSTATE, pfnSaveGlobalState, p, (pSaveData));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_RestoreGlobalState(SAVERESTOREDATA *pSaveData) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_RESTOREGLOBALSTATE, pfnRestoreGlobalState, p, (pSaveData));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_ResetGlobalState(void) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_RESETGLOBALSTATE, pfnResetGlobalState, void, (VOID_ARG));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
|
|
||||||
// From SDK dlls/client.cpp:
|
|
||||||
static qboolean mm_ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]) {
|
|
||||||
g_Players.clear_player_cvar_query(pEntity);
|
|
||||||
META_DLLAPI_HANDLE(qboolean, TRUE, FN_CLIENTCONNECT, pfnClientConnect, 4p, (pEntity, pszName, pszAddress, szRejectReason));
|
|
||||||
RETURN_API(qboolean);
|
|
||||||
}
|
|
||||||
static void mm_ClientDisconnect(edict_t *pEntity) {
|
|
||||||
g_Players.clear_player_cvar_query(pEntity);
|
|
||||||
META_DLLAPI_HANDLE_void(FN_CLIENTDISCONNECT, pfnClientDisconnect, p, (pEntity));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_ClientKill(edict_t *pEntity) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_CLIENTKILL, pfnClientKill, p, (pEntity));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_ClientPutInServer(edict_t *pEntity) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_CLIENTPUTINSERVER, pfnClientPutInServer, p, (pEntity));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_ClientCommand(edict_t *pEntity) {
|
|
||||||
if(Config->clientmeta && strmatch(CMD_ARGV(0), "meta")) {
|
|
||||||
client_meta(pEntity);
|
|
||||||
}
|
|
||||||
META_DLLAPI_HANDLE_void(FN_CLIENTCOMMAND, pfnClientCommand, p, (pEntity));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_ClientUserInfoChanged(edict_t *pEntity, char *infobuffer) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_CLIENTUSERINFOCHANGED, pfnClientUserInfoChanged, 2p, (pEntity, infobuffer));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_SERVERACTIVATE, pfnServerActivate, p2i, (pEdictList, edictCount, clientMax));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_ServerDeactivate(void) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_SERVERDEACTIVATE, pfnServerDeactivate, void, (VOID_ARG));
|
|
||||||
// Update loaded plugins. Look for new plugins in inifile, as well as
|
|
||||||
// any plugins waiting for a changelevel to load.
|
|
||||||
//
|
|
||||||
// This is done in ServerDeactivate rather than Activate, as the latter
|
|
||||||
// isn't actually the first routine to be called on a new map. In
|
|
||||||
// particular DispatchKeyValue and DispatchSpawn are called before
|
|
||||||
// Activate, and we want any newly loaded plugins to be able to catch
|
|
||||||
// these.
|
|
||||||
//
|
|
||||||
// So, we do this from Deactivate, which is the _last_ routine called
|
|
||||||
// from the previous map. It's also called right before shutdown,
|
|
||||||
// which means whenever hlds quits, it'll reload the plugins just
|
|
||||||
// before it exits, which is rather silly, but oh well.
|
|
||||||
Plugins->refresh(PT_CHANGELEVEL);
|
|
||||||
Plugins->unpause_all();
|
|
||||||
// Plugins->retry_all(PT_CHANGELEVEL);
|
|
||||||
g_Players.clear_all_cvar_queries();
|
|
||||||
requestid_counter = 0;
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_PlayerPreThink(edict_t *pEntity) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_PLAYERPRETHINK, pfnPlayerPreThink, p, (pEntity));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_PlayerPostThink(edict_t *pEntity) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_PLAYERPOSTTHINK, pfnPlayerPostThink, p, (pEntity));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_StartFrame(void) {
|
|
||||||
meta_debug_value = (int)meta_debug.value;
|
|
||||||
|
|
||||||
META_DLLAPI_HANDLE_void(FN_STARTFRAME, pfnStartFrame, void, (VOID_ARG));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_ParmsNewLevel(void) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_PARMSNEWLEVEL, pfnParmsNewLevel, void, (VOID_ARG));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_ParmsChangeLevel(void) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_PARMSCHANGELEVEL, pfnParmsChangeLevel, void, (VOID_ARG));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static const char *mm_GetGameDescription(void) {
|
|
||||||
META_DLLAPI_HANDLE(const char *, NULL, FN_GETGAMEDESCRIPTION, pfnGetGameDescription, void, (VOID_ARG));
|
|
||||||
RETURN_API(const char *);
|
|
||||||
}
|
|
||||||
static void mm_PlayerCustomization(edict_t *pEntity, customization_t *pCust) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_PLAYERCUSTOMIZATION, pfnPlayerCustomization, 2p, (pEntity, pCust));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_SpectatorConnect(edict_t *pEntity) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_SPECTATORCONNECT, pfnSpectatorConnect, p, (pEntity));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_SpectatorDisconnect(edict_t *pEntity) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_SPECTATORDISCONNECT, pfnSpectatorDisconnect, p, (pEntity));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_SpectatorThink(edict_t *pEntity) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_SPECTATORTHINK, pfnSpectatorThink, p, (pEntity));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_Sys_Error(const char *error_string) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_SYS_ERROR, pfnSys_Error, p, (error_string));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
|
|
||||||
// From SDK pm_shared/pm_shared.c:
|
|
||||||
static void mm_PM_Move (struct playermove_s *ppmove, int server) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_PM_MOVE, pfnPM_Move, pi, (ppmove, server));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_PM_Init(struct playermove_s *ppmove) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_PM_INIT, pfnPM_Init, p, (ppmove));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static char mm_PM_FindTextureType(char *name) {
|
|
||||||
META_DLLAPI_HANDLE(char, '\0', FN_PM_FINDTEXTURETYPE, pfnPM_FindTextureType, p, (name));
|
|
||||||
RETURN_API(char);
|
|
||||||
}
|
|
||||||
|
|
||||||
// From SDK dlls/client.cpp:
|
|
||||||
static void mm_SetupVisibility(edict_t *pViewEntity, edict_t *pClient, unsigned char **pvs, unsigned char **pas) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_SETUPVISIBILITY, pfnSetupVisibility, 4p, (pViewEntity, pClient, pvs, pas));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_UpdateClientData (const struct edict_s *ent, int sendweapons, struct clientdata_s *cd) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_UPDATECLIENTDATA, pfnUpdateClientData, pip, (ent, sendweapons, cd));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static int mm_AddToFullPack(struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet) {
|
|
||||||
META_DLLAPI_HANDLE(int, 0, FN_ADDTOFULLPACK, pfnAddToFullPack, pi2p2ip, (state, e, ent, host, hostflags, player, pSet));
|
|
||||||
RETURN_API(int);
|
|
||||||
}
|
|
||||||
static void mm_CreateBaseline(int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_CREATEBASELINE, pfnCreateBaseline, 2i2pi2p, (player, eindex, baseline, entity, playermodelindex, (float*)player_mins, (float*)player_maxs));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_RegisterEncoders(void) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_REGISTERENCODERS, pfnRegisterEncoders, void, (VOID_ARG));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static int mm_GetWeaponData(struct edict_s *player, struct weapon_data_s *info) {
|
|
||||||
META_DLLAPI_HANDLE(int, 0, FN_GETWEAPONDATA, pfnGetWeaponData, 2p, (player, info));
|
|
||||||
RETURN_API(int);
|
|
||||||
}
|
|
||||||
static void mm_CmdStart(const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_CMDSTART, pfnCmdStart, 2pui, (player, cmd, random_seed));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_CmdEnd (const edict_t *player) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_CMDEND, pfnCmdEnd, p, (player));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static int mm_ConnectionlessPacket(const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size) {
|
|
||||||
META_DLLAPI_HANDLE(int, 0, FN_CONNECTIONLESSPACKET, pfnConnectionlessPacket, 4p, (net_from, args, response_buffer, response_buffer_size));
|
|
||||||
RETURN_API(int);
|
|
||||||
}
|
|
||||||
static int mm_GetHullBounds(int hullnumber, float *mins, float *maxs) {
|
|
||||||
META_DLLAPI_HANDLE(int, 0, FN_GETHULLBOUNDS, pfnGetHullBounds, i2p, (hullnumber, mins, maxs));
|
|
||||||
RETURN_API(int);
|
|
||||||
}
|
|
||||||
static void mm_CreateInstancedBaselines (void) {
|
|
||||||
META_DLLAPI_HANDLE_void(FN_CREATEINSTANCEDBASELINES, pfnCreateInstancedBaselines, void, (VOID_ARG));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static int mm_InconsistentFile(const edict_t *player, const char *filename, char *disconnect_message) {
|
|
||||||
META_DLLAPI_HANDLE(int, 0, FN_INCONSISTENTFILE, pfnInconsistentFile, 3p, (player, filename, disconnect_message));
|
|
||||||
RETURN_API(int);
|
|
||||||
}
|
|
||||||
static int mm_AllowLagCompensation(void) {
|
|
||||||
META_DLLAPI_HANDLE(int, 0, FN_ALLOWLAGCOMPENSATION, pfnAllowLagCompensation, void, (VOID_ARG));
|
|
||||||
RETURN_API(int);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// New API functions
|
|
||||||
// From SDK ?
|
|
||||||
static void mm_OnFreeEntPrivateData(edict_t *pEnt) {
|
|
||||||
META_NEWAPI_HANDLE_void(FN_ONFREEENTPRIVATEDATA, pfnOnFreeEntPrivateData, p, (pEnt));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static void mm_GameShutdown(void) {
|
|
||||||
META_NEWAPI_HANDLE_void(FN_GAMESHUTDOWN, pfnGameShutdown, void, (VOID_ARG));
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
static int mm_ShouldCollide(edict_t *pentTouched, edict_t *pentOther) {
|
|
||||||
META_NEWAPI_HANDLE(int, 1, FN_SHOULDCOLLIDE, pfnShouldCollide, 2p, (pentTouched, pentOther));
|
|
||||||
RETURN_API(int);
|
|
||||||
}
|
|
||||||
// Added 2005/08/11 (no SDK update):
|
|
||||||
static void mm_CvarValue(const edict_t *pEnt, const char *value) {
|
|
||||||
g_Players.clear_player_cvar_query(pEnt);
|
|
||||||
META_NEWAPI_HANDLE_void(FN_CVARVALUE, pfnCvarValue, 2p, (pEnt, value));
|
|
||||||
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
// Added 2005/11/21 (no SDK update):
|
|
||||||
static void mm_CvarValue2(const edict_t *pEnt, int requestID, const char *cvarName, const char *value) {
|
|
||||||
META_NEWAPI_HANDLE_void(FN_CVARVALUE2, pfnCvarValue2, pi2p, (pEnt, requestID, cvarName, value));
|
|
||||||
|
|
||||||
RETURN_API_void();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// From SDK dlls/cbase.cpp:
|
|
||||||
// "(wd)" indicates my comments on the functions
|
|
||||||
static DLL_FUNCTIONS gFunctionTable =
|
|
||||||
{
|
|
||||||
mm_GameDLLInit, //! pfnGameInit() Initialize the game (one-time call after loading of game .dll)
|
|
||||||
mm_DispatchSpawn, //! pfnSpawn()
|
|
||||||
mm_DispatchThink, //! pfnThink()
|
|
||||||
mm_DispatchUse, //! pfnUse()
|
|
||||||
mm_DispatchTouch, //! pfnTouch()
|
|
||||||
mm_DispatchBlocked, //! pfnBlocked()
|
|
||||||
mm_DispatchKeyValue, //! pfnKeyValue()
|
|
||||||
mm_DispatchSave, //! pfnSave()
|
|
||||||
mm_DispatchRestore, //! pfnRestore()
|
|
||||||
mm_DispatchObjectCollsionBox, //! pfnSetAbsBox()
|
|
||||||
|
|
||||||
mm_SaveWriteFields, //! pfnSaveWriteFields()
|
|
||||||
mm_SaveReadFields, //! pfnSaveReadFields()
|
|
||||||
|
|
||||||
mm_SaveGlobalState, //! pfnSaveGlobalState()
|
|
||||||
mm_RestoreGlobalState, //! pfnRestoreGlobalState()
|
|
||||||
mm_ResetGlobalState, //! pfnResetGlobalState()
|
|
||||||
|
|
||||||
mm_ClientConnect, //! pfnClientConnect() (wd) Client has connected
|
|
||||||
mm_ClientDisconnect, //! pfnClientDisconnect() (wd) Player has left the game
|
|
||||||
mm_ClientKill, //! pfnClientKill() (wd) Player has typed "kill"
|
|
||||||
mm_ClientPutInServer, //! pfnClientPutInServer() (wd) Client is entering the game
|
|
||||||
mm_ClientCommand, //! pfnClientCommand() (wd) Player has sent a command (typed, or from a bind)
|
|
||||||
mm_ClientUserInfoChanged, //! pfnClientUserInfoChanged() (wd) Client has updated their setinfo structure
|
|
||||||
mm_ServerActivate, //! pfnServerActivate() (wd) Server is starting a new map
|
|
||||||
mm_ServerDeactivate, //! pfnServerDeactivate() (wd) Server is leaving the map (shutdown, or changelevel); SDK2
|
|
||||||
|
|
||||||
mm_PlayerPreThink, //! pfnPlayerPreThink()
|
|
||||||
mm_PlayerPostThink, //! pfnPlayerPostThink()
|
|
||||||
|
|
||||||
mm_StartFrame, //! pfnStartFrame()
|
|
||||||
mm_ParmsNewLevel, //! pfnParmsNewLevel()
|
|
||||||
mm_ParmsChangeLevel, //! pfnParmsChangeLevel()
|
|
||||||
|
|
||||||
mm_GetGameDescription, //! pfnGetGameDescription() Returns string describing current .dll. E.g. "TeamFotrress 2", "Half-Life"
|
|
||||||
mm_PlayerCustomization, //! pfnPlayerCustomization() Notifies .dll of new customization for player.
|
|
||||||
|
|
||||||
mm_SpectatorConnect, //! pfnSpectatorConnect() Called when spectator joins server
|
|
||||||
mm_SpectatorDisconnect, //! pfnSpectatorDisconnect() Called when spectator leaves the server
|
|
||||||
mm_SpectatorThink, //! pfnSpectatorThink() Called when spectator sends a command packet (usercmd_t)
|
|
||||||
|
|
||||||
mm_Sys_Error, //! pfnSys_Error() Notify game .dll that engine is going to shut down. Allows mod authors to set a breakpoint. SDK2
|
|
||||||
|
|
||||||
mm_PM_Move, //! pfnPM_Move() (wd) SDK2
|
|
||||||
mm_PM_Init, //! pfnPM_Init() Server version of player movement initialization; (wd) SDK2
|
|
||||||
mm_PM_FindTextureType, //! pfnPM_FindTextureType() (wd) SDK2
|
|
||||||
|
|
||||||
mm_SetupVisibility, //! pfnSetupVisibility() Set up PVS and PAS for networking for this client; (wd) SDK2
|
|
||||||
mm_UpdateClientData, //! pfnUpdateClientData() Set up data sent only to specific client; (wd) SDK2
|
|
||||||
mm_AddToFullPack, //! pfnAddToFullPack() (wd) SDK2
|
|
||||||
mm_CreateBaseline, //! pfnCreateBaseline() Tweak entity baseline for network encoding, allows setup of player baselines, too.; (wd) SDK2
|
|
||||||
mm_RegisterEncoders, //! pfnRegisterEncoders() Callbacks for network encoding; (wd) SDK2
|
|
||||||
mm_GetWeaponData, //! pfnGetWeaponData() (wd) SDK2
|
|
||||||
mm_CmdStart, //! pfnCmdStart() (wd) SDK2
|
|
||||||
mm_CmdEnd, //! pfnCmdEnd() (wd) SDK2
|
|
||||||
mm_ConnectionlessPacket, //! pfnConnectionlessPacket() (wd) SDK2
|
|
||||||
mm_GetHullBounds, //! pfnGetHullBounds() (wd) SDK2
|
|
||||||
mm_CreateInstancedBaselines, //! pfnCreateInstancedBaselines() (wd) SDK2
|
|
||||||
mm_InconsistentFile, //! pfnInconsistentFile() (wd) SDK2
|
|
||||||
mm_AllowLagCompensation, //! pfnAllowLagCompensation() (wd) SDK2
|
|
||||||
};
|
|
||||||
|
|
||||||
DLL_FUNCTIONS *g_pHookedDllFunctions = &gFunctionTable;
|
|
||||||
|
|
||||||
// It's not clear what the difference is between GetAPI and GetAPI2; they
|
|
||||||
// both appear to return the exact same function table.
|
|
||||||
//
|
|
||||||
// Only one of them appears to be ever called, though. If the DLL provides
|
|
||||||
// GetAPI2, the engine/hlds will call that, and will not call GetAPI. If
|
|
||||||
// the engine couldn't find GetAPI2 in the DLL, it appears to fall back to
|
|
||||||
// GetAPI.
|
|
||||||
//
|
|
||||||
// So, GetAPI2 appears to replace GetAPI, and appears to have been added
|
|
||||||
// with SDK 2.0. My best guess is that, with the new SDK, interface
|
|
||||||
// version checking became important, and without the int ptr used in
|
|
||||||
// GetAPI2, the engine can't find out the version of the DLL via GetAPI.
|
|
||||||
//
|
|
||||||
// It's unclear whether a DLL coded under SDK2 needs to provide the older
|
|
||||||
// GetAPI or not..
|
|
||||||
|
|
||||||
C_DLLEXPORT int GetEntityAPI(DLL_FUNCTIONS *pFunctionTable, int interfaceVersion)
|
|
||||||
{
|
|
||||||
META_DEBUG(3, ("called: GetEntityAPI; version=%d", interfaceVersion));
|
|
||||||
if(!pFunctionTable || metamod_not_loaded) {
|
|
||||||
META_WARNING("GetEntityAPI called with null pFunctionTable");
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
else if(interfaceVersion != INTERFACE_VERSION) {
|
|
||||||
META_WARNING("GetEntityAPI version mismatch; requested=%d ours=%d", interfaceVersion, INTERFACE_VERSION);
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS));
|
|
||||||
return(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
C_DLLEXPORT int GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion)
|
|
||||||
{
|
|
||||||
META_DEBUG(3, ("called: GetEntityAPI2; version=%d", *interfaceVersion));
|
|
||||||
if(!pFunctionTable || metamod_not_loaded) {
|
|
||||||
META_WARNING("GetEntityAPI2 called with null pFunctionTable");
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
else if(*interfaceVersion != INTERFACE_VERSION) {
|
|
||||||
META_WARNING("GetEntityAPI2 version mismatch; requested=%d ours=%d", *interfaceVersion, INTERFACE_VERSION);
|
|
||||||
//! Tell engine what version we had, so it can figure out who is out of date.
|
|
||||||
*interfaceVersion = INTERFACE_VERSION;
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS));
|
|
||||||
return(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// I could find _no_ documentation or examples for the intended use of
|
|
||||||
// NEW_DLL_FUNCTIONS. I wouldn't have even _known_ about the
|
|
||||||
// GetNewDLLFunctions() function except for the reference in Adminmod.. It
|
|
||||||
// appears to be new with SDK 2.0.
|
|
||||||
//
|
|
||||||
// Obviously, it seems to provide additional functions to the engine, but
|
|
||||||
// it's unclear why a new table and interface were added, rather than
|
|
||||||
// appending new functions to the GetAPI table/interface.
|
|
||||||
//
|
|
||||||
// Interestingly, it appears to be called by the engine _before_ GetAPI.
|
|
||||||
|
|
||||||
static meta_new_dll_functions_t sNewFunctionTable(
|
|
||||||
&mm_OnFreeEntPrivateData, //! pfnOnFreeEntPrivateData() Called right before the object's memory is freed. Calls its destructor.
|
|
||||||
&mm_GameShutdown, //! pfnGameShutdown()
|
|
||||||
&mm_ShouldCollide, //! pfnShouldCollide()
|
|
||||||
// Added 2005/08/11 (no SDK update):
|
|
||||||
&mm_CvarValue, //! pfnCvarValue()
|
|
||||||
// Added 2005/11/21 (no SDK update):
|
|
||||||
&mm_CvarValue2 //! pfnCvarValue2()
|
|
||||||
);
|
|
||||||
|
|
||||||
NEW_DLL_FUNCTIONS *g_pHookedNewDllFunctions = &sNewFunctionTable;
|
|
||||||
|
|
||||||
C_DLLEXPORT int GetNewDLLFunctions(NEW_DLL_FUNCTIONS *pNewFunctionTable, int *interfaceVersion)
|
|
||||||
{
|
|
||||||
META_DEBUG(6, ("called: GetNewDLLFunctions; version=%d", *interfaceVersion));
|
|
||||||
#if 0 // ~dvander - but then you can't use cvar querying on many mods...
|
|
||||||
// Don't provide these functions to engine if gamedll doesn't provide
|
|
||||||
// them. Otherwise, we're in the position of having to provide answers
|
|
||||||
// we can't necessarily provide (for instance, ShouldCollide())...
|
|
||||||
if(!GameDLL.funcs.newapi_table)
|
|
||||||
return(FALSE);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if(!pNewFunctionTable) {
|
|
||||||
META_ERROR("GetNewDLLFunctions called with null pNewFunctionTable");
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
else if(*interfaceVersion != NEW_DLL_FUNCTIONS_VERSION) {
|
|
||||||
META_ERROR("GetNewDLLFunctions version mismatch; requested=%d ours=%d", *interfaceVersion, NEW_DLL_FUNCTIONS_VERSION);
|
|
||||||
//! Tell engine what version we had, so it can figure out who is out of date.
|
|
||||||
*interfaceVersion = NEW_DLL_FUNCTIONS_VERSION;
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
sNewFunctionTable.copy_to(pNewFunctionTable);
|
|
||||||
|
|
||||||
|
|
||||||
return(TRUE);
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,7 @@
|
|||||||
#ifndef ENGINE_API_H
|
#ifndef ENGINE_API_H
|
||||||
#define ENGINE_API_H
|
#define ENGINE_API_H
|
||||||
|
|
||||||
|
#include <stdint.h> // why?
|
||||||
#include "comp_dep.h"
|
#include "comp_dep.h"
|
||||||
|
|
||||||
// Plugin's GetEngineFunctions, called by metamod.
|
// Plugin's GetEngineFunctions, called by metamod.
|
||||||
@@ -125,7 +126,7 @@ typedef void (*FN_ENGINEFPRINTF) (FILE *pfile, char *szFmt, ...);
|
|||||||
typedef void * (*FN_PVALLOCENTPRIVATEDATA) (edict_t *pEdict, long cb);
|
typedef void * (*FN_PVALLOCENTPRIVATEDATA) (edict_t *pEdict, long cb);
|
||||||
#else
|
#else
|
||||||
typedef void (*FN_ENGINEFPRINTF) (void *pfile, char *szFmt, ...);
|
typedef void (*FN_ENGINEFPRINTF) (void *pfile, char *szFmt, ...);
|
||||||
typedef void * (*FN_PVALLOCENTPRIVATEDATA) (edict_t *pEdict, int32 cb);
|
typedef void * (*FN_PVALLOCENTPRIVATEDATA) (edict_t *pEdict, int32_t cb);
|
||||||
#endif
|
#endif
|
||||||
typedef void * (*FN_PVENTPRIVATEDATA) (edict_t *pEdict);
|
typedef void * (*FN_PVENTPRIVATEDATA) (edict_t *pEdict);
|
||||||
typedef void (*FN_FREEENTPRIVATEDATA) (edict_t *pEdict);
|
typedef void (*FN_FREEENTPRIVATEDATA) (edict_t *pEdict);
|
||||||
@@ -145,8 +146,8 @@ typedef void (*FN_GETBONEPOSITION) (const edict_t *pEdict, int iBone, float *rgf
|
|||||||
typedef unsigned long (*FN_FUNCTIONFROMNAME) ( const char *pName );
|
typedef unsigned long (*FN_FUNCTIONFROMNAME) ( const char *pName );
|
||||||
typedef const char * (*FN_NAMEFORFUNCTION) ( unsigned long function );
|
typedef const char * (*FN_NAMEFORFUNCTION) ( unsigned long function );
|
||||||
#else
|
#else
|
||||||
typedef uint32 (*FN_FUNCTIONFROMNAME) ( const char *pName );
|
typedef uint32_t (*FN_FUNCTIONFROMNAME) ( const char *pName );
|
||||||
typedef const char * (*FN_NAMEFORFUNCTION) ( uint32 function );
|
typedef const char * (*FN_NAMEFORFUNCTION) ( uint32_t function );
|
||||||
#endif
|
#endif
|
||||||
typedef void (*FN_CLIENTPRINTF) ( edict_t *pEdict, PRINT_TYPE ptype, const char *szMsg );
|
typedef void (*FN_CLIENTPRINTF) ( edict_t *pEdict, PRINT_TYPE ptype, const char *szMsg );
|
||||||
typedef void (*FN_SERVERPRINT) ( const char *szMsg );
|
typedef void (*FN_SERVERPRINT) ( const char *szMsg );
|
||||||
@@ -161,7 +162,7 @@ typedef CRC32_t (*FN_CRC32_FINAL) (CRC32_t pulCRC);
|
|||||||
#ifdef HLSDK_3_2_OLD_EIFACE
|
#ifdef HLSDK_3_2_OLD_EIFACE
|
||||||
typedef long (*FN_RANDOMLONG) (long lLow, long lHigh);
|
typedef long (*FN_RANDOMLONG) (long lLow, long lHigh);
|
||||||
#else
|
#else
|
||||||
typedef int32 (*FN_RANDOMLONG) (int32 lLow, int32 lHigh);
|
typedef int32_t (*FN_RANDOMLONG) (int32_t lLow, int32_t lHigh);
|
||||||
#endif
|
#endif
|
||||||
typedef float (*FN_RANDOMFLOAT) (float flLow, float flHigh);
|
typedef float (*FN_RANDOMFLOAT) (float flLow, float flHigh);
|
||||||
typedef void (*FN_SETVIEW) (const edict_t *pClient, const edict_t *pViewent );
|
typedef void (*FN_SETVIEW) (const edict_t *pClient, const edict_t *pViewent );
|
||||||
|
|||||||
@@ -1,390 +0,0 @@
|
|||||||
|
|
||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// engineinfo.cpp - get info about HL engine, like file used
|
|
||||||
// and test segment range
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
// Don't include winspool.h; clashes with SERVER_EXECUTE from engine
|
|
||||||
# define _WINSPOOL_H
|
|
||||||
# include <windows.h>
|
|
||||||
# include <winnt.h> // Header structures
|
|
||||||
#else
|
|
||||||
# ifndef _GNU_SOURCE
|
|
||||||
# define _GNU_SOURCE
|
|
||||||
# endif
|
|
||||||
# include <dlfcn.h> // dladdr()
|
|
||||||
# include <link.h> // ElfW(Phdr/Ehdr) macros.
|
|
||||||
// _DYNAMIC, r_debug, link_map, etc.
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
#include <string.h> // strlen(), strrchr(), strcmp()
|
|
||||||
#include <stdio.h> // printf()
|
|
||||||
|
|
||||||
#include "engineinfo.h" // me
|
|
||||||
#include "log_meta.h" // META_DEV()
|
|
||||||
|
|
||||||
|
|
||||||
// Current mask for checking engine function addresses
|
|
||||||
// in VAC protected engine dlls on Win32. This is gonna fail
|
|
||||||
// on Win64.
|
|
||||||
const unsigned long c_VacDllEngineFuncsRangeMask = 0xFFF00000;
|
|
||||||
const unsigned long c_VacDllEngineFuncsRangeMark = 0x01D00000;
|
|
||||||
void* const c_VacDllEngineFuncsRangeStart = (void*)0x01D00000;
|
|
||||||
void* const c_VacDllEngineFuncsRangeEnd = (void*)0x01E00000;
|
|
||||||
|
|
||||||
|
|
||||||
bool DLLINTERNAL EngineInfo::check_for_engine_module( const char* _pName )
|
|
||||||
{
|
|
||||||
const char* pC;
|
|
||||||
size_t size;
|
|
||||||
|
|
||||||
if ( NULL == _pName ) return false;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
// The engine module is either sw.dll or hw.dll or swds.dll
|
|
||||||
pC = strrchr( _pName, '.' );
|
|
||||||
|
|
||||||
pC -= 2;
|
|
||||||
if ( 0 != strcmp(pC, "sw.dll") && 0 != strcmp(pC, "hw.dll") ) {
|
|
||||||
pC -= 2;
|
|
||||||
if ( 0 != strcmp(pC, "swds.dll") ) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
HMODULE hModule = GetModuleHandle( pC );
|
|
||||||
if ( NULL == hModule ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ok, we found the string sw(ds).dll, thus we deduct that this is the
|
|
||||||
// name of the engine's shared object. We copy the string for future
|
|
||||||
// reference and return successfully.
|
|
||||||
size = 0;
|
|
||||||
while ( *pC != '.' && size < c_EngineInfo__typeLen-1 ) {
|
|
||||||
m_type[size++] = *pC++;
|
|
||||||
}
|
|
||||||
m_type[size] = '\0';
|
|
||||||
|
|
||||||
#else /* _WIN32 */
|
|
||||||
|
|
||||||
const char* pType;
|
|
||||||
|
|
||||||
|
|
||||||
size = strlen( _pName );
|
|
||||||
if ( size < 11 ) {
|
|
||||||
// Forget it, this string is too short to even be 'engine_.so', so
|
|
||||||
// it can't the name of the engine shared library.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start parsing at the end. Since we know that the string is at least
|
|
||||||
// 11 characters long we can safely do our parsing without being afraid
|
|
||||||
// of leaving the string.
|
|
||||||
pC = _pName + size -1;
|
|
||||||
|
|
||||||
// First we see if the string ends in '.so'
|
|
||||||
if ( *pC-- != 'o' || *pC-- != 's' || *pC-- != '.' ) return false;
|
|
||||||
|
|
||||||
// Now find the '_' which would be the seperator between 'engine' and
|
|
||||||
// the architecture.
|
|
||||||
while ( *pC != '_' && pC != _pName ) --pC;
|
|
||||||
if ( pC == _pName ) return false;
|
|
||||||
|
|
||||||
// We are at the '_', thus the architecture identifier must start at
|
|
||||||
// the next character.
|
|
||||||
pType = pC +1;
|
|
||||||
|
|
||||||
// Now we walk further back and check if we find the string 'engine'
|
|
||||||
// backwards.
|
|
||||||
--pC;
|
|
||||||
if ( *pC-- != 'e' || *pC-- != 'n' || *pC-- != 'i' ||
|
|
||||||
*pC-- != 'g' || *pC-- != 'n' || *pC != 'e' ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ok, we found the string engine_*.so, thus we deduct that this is the
|
|
||||||
// name of the engine's shared object. We copy the architecture string
|
|
||||||
// for future reference and return successfully.
|
|
||||||
size = 0;
|
|
||||||
while ( *pType != '.' && size < c_EngineInfo__typeLen-1 ) {
|
|
||||||
m_type[size++] = *pType++;
|
|
||||||
}
|
|
||||||
m_type[size] = '\0';
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
int DLLINTERNAL EngineInfo::nthdr_module_name( void )
|
|
||||||
{
|
|
||||||
PIMAGE_DOS_HEADER pDosHeader;
|
|
||||||
PIMAGE_NT_HEADERS pNTHeader;
|
|
||||||
unsigned char* pBaseAddr;
|
|
||||||
const char* pName = "sw.dll";
|
|
||||||
|
|
||||||
if ( ! check_for_engine_module(pName) ) {
|
|
||||||
pName = "hw.dll";
|
|
||||||
if ( ! check_for_engine_module(pName) ) {
|
|
||||||
pName = "swds.dll";
|
|
||||||
if ( ! check_for_engine_module(pName) ) {
|
|
||||||
return MODULE_NAME_NOTFOUND;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the module handle for the engine dll we found.
|
|
||||||
// This is also the modules base address.
|
|
||||||
HMODULE hModule = GetModuleHandle( pName );
|
|
||||||
|
|
||||||
pBaseAddr = (unsigned char*)hModule;
|
|
||||||
|
|
||||||
|
|
||||||
// Check if we find a DOS header
|
|
||||||
pDosHeader = (PIMAGE_DOS_HEADER)hModule;
|
|
||||||
if ( pDosHeader->e_magic != IMAGE_DOS_SIGNATURE ) {
|
|
||||||
return INVALID_DOS_SIGN;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we find a PE header
|
|
||||||
pNTHeader = (PIMAGE_NT_HEADERS)(pBaseAddr + pDosHeader->e_lfanew);
|
|
||||||
if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE ) {
|
|
||||||
return INVALID_NT_SIGN;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_code_range( pBaseAddr, pNTHeader );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int DLLINTERNAL EngineInfo::vac_pe_approx( enginefuncs_t* _pFuncs )
|
|
||||||
{
|
|
||||||
if ( NULL == _pFuncs ) return INVALID_ARG;
|
|
||||||
|
|
||||||
// There is really no good and easy way to do this. Right now what
|
|
||||||
// we do is assume that Steam listenservers will normally be
|
|
||||||
// up-to-date and hence have all function pointers set correctly.
|
|
||||||
// So we just check for some anomality and then set some approximated
|
|
||||||
// values.
|
|
||||||
|
|
||||||
// The known addresses at the time of writing all start with 0x01D and
|
|
||||||
// this lie in the range between 0x01D00000 and 0x01E00000. What we do
|
|
||||||
// is check all functions pointers that are known to be good to start
|
|
||||||
// with 0x01D. If that is the case then we know that the loading address
|
|
||||||
// of the engine functions hasn't changed and we assume the above stated
|
|
||||||
// range to be the range of valid engine function addresses.
|
|
||||||
// If we find functions outside this range we can't determine a valid
|
|
||||||
// range and have to just give up.
|
|
||||||
|
|
||||||
unsigned long* pengfuncs = (unsigned long*)_pFuncs;
|
|
||||||
unsigned int i, invals = 0;
|
|
||||||
for ( i = 0, pengfuncs += i; i < 140; i++, pengfuncs++ ) {
|
|
||||||
if ( ((*pengfuncs) & c_VacDllEngineFuncsRangeMask) != c_VacDllEngineFuncsRangeMark ) {
|
|
||||||
invals++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( invals > 0 ) {
|
|
||||||
META_DEV( "Found %d engine functions out of range 0x%08lx. "
|
|
||||||
"Unable to determine valid engine code address range.",
|
|
||||||
invals, c_VacDllEngineFuncsRangeMark );
|
|
||||||
|
|
||||||
strncpy( m_type, "vacdll+?", c_EngineInfo__typeLen );
|
|
||||||
m_state = STATE_INVALID;
|
|
||||||
return STATE_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_codeStart = c_VacDllEngineFuncsRangeStart;
|
|
||||||
m_codeEnd = c_VacDllEngineFuncsRangeEnd;
|
|
||||||
|
|
||||||
strncpy( m_type, "vacdll", c_EngineInfo__typeLen );
|
|
||||||
|
|
||||||
m_state = STATE_VALID;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DLLINTERNAL EngineInfo::set_code_range( unsigned char* _pBase, PIMAGE_NT_HEADERS _pNThdr )
|
|
||||||
{
|
|
||||||
m_codeStart = _pBase + _pNThdr->OptionalHeader.BaseOfCode;
|
|
||||||
m_codeEnd = _pBase + _pNThdr->OptionalHeader.BaseOfCode + _pNThdr->OptionalHeader.SizeOfCode;
|
|
||||||
|
|
||||||
m_state = STATE_VALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#else /* _WIN32 */
|
|
||||||
|
|
||||||
|
|
||||||
int DLLINTERNAL EngineInfo::phdr_elfhdr( void* _pElfHdr )
|
|
||||||
{
|
|
||||||
ElfW(Ehdr)* pEhdr = (ElfW(Ehdr)*)_pElfHdr;
|
|
||||||
ElfW(Phdr)* pPhdr;
|
|
||||||
|
|
||||||
if ( NULL == _pElfHdr ) return INVALID_ARG;
|
|
||||||
|
|
||||||
if ( pEhdr->e_ident[0] == 0x7f
|
|
||||||
&& pEhdr->e_ident[1] == 'E'
|
|
||||||
&& pEhdr->e_ident[2] == 'L'
|
|
||||||
&& pEhdr->e_ident[3] == 'F' ) {
|
|
||||||
|
|
||||||
// Looking good, we found an ELF signature.
|
|
||||||
// Let's see if the rest of the data at this address would fit an ELH header, too.
|
|
||||||
if ( (pEhdr->e_ident[EI_CLASS] == ELFCLASS32 //ELFW(CLASS)
|
|
||||||
|| pEhdr->e_ident[EI_CLASS] == ELFCLASS64)
|
|
||||||
|
|
||||||
&& (pEhdr->e_ident[EI_DATA] == ELFDATA2LSB
|
|
||||||
|| pEhdr->e_ident[EI_DATA] == ELFDATA2MSB)
|
|
||||||
|
|
||||||
&& pEhdr->e_type == ET_DYN ) {
|
|
||||||
|
|
||||||
// Ok, we believe that this is a shared object's ELF header.
|
|
||||||
// Let's find the program header for the segment that includes
|
|
||||||
// the text section and return it.
|
|
||||||
|
|
||||||
pPhdr = (ElfW(Phdr) *) ((char *) pEhdr + pEhdr->e_phoff);
|
|
||||||
for ( int i = 0; i < pEhdr->e_phnum; i++, pPhdr++ ) {
|
|
||||||
|
|
||||||
if ( PT_LOAD == pPhdr->p_type
|
|
||||||
&& (pPhdr->p_flags & PF_R)
|
|
||||||
&& (pPhdr->p_flags & PF_X) ) {
|
|
||||||
|
|
||||||
// The text section gets loaded and has read and
|
|
||||||
// execute flags set. So this must be it.
|
|
||||||
set_code_range( pEhdr, pPhdr );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return HEADER_NOTFOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int DLLINTERNAL EngineInfo::phdr_dladdr( void* _pMem )
|
|
||||||
{
|
|
||||||
Dl_info info;
|
|
||||||
|
|
||||||
if ( 0 != dladdr(_pMem, &info) ) {
|
|
||||||
// Check if this is the engine module
|
|
||||||
if ( check_for_engine_module(info.dli_fname) ) {
|
|
||||||
return phdr_elfhdr( info.dli_fbase );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NOTFOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int DLLINTERNAL EngineInfo::phdr_r_debug( void )
|
|
||||||
{
|
|
||||||
ElfW(Dyn)* pDyn;
|
|
||||||
struct r_debug* pr_debug;
|
|
||||||
struct link_map* pMap;
|
|
||||||
|
|
||||||
|
|
||||||
// Search if we have a DT_DEBUG symbol in our DYNAMIC segment, which
|
|
||||||
// ought to be set to the r_debug structure's address.
|
|
||||||
for (pDyn = _DYNAMIC; pDyn->d_tag != DT_NULL; ++pDyn) {
|
|
||||||
if (pDyn->d_tag == DT_DEBUG) {
|
|
||||||
pr_debug = (struct r_debug *) pDyn->d_un.d_ptr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( DT_NULL == pDyn->d_tag ) {
|
|
||||||
}
|
|
||||||
else if ( NULL == pr_debug ) {
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
pMap = pr_debug->r_map;
|
|
||||||
|
|
||||||
// Walk to the start of the list
|
|
||||||
while ( pMap->l_prev != NULL ) pMap = pMap->l_prev;
|
|
||||||
do {
|
|
||||||
if ( check_for_engine_module(pMap->l_name) ) {
|
|
||||||
return phdr_elfhdr( (void*)pMap->l_addr );
|
|
||||||
}
|
|
||||||
|
|
||||||
pMap = pMap->l_next;
|
|
||||||
} while ( NULL != pMap );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return NOTFOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DLLINTERNAL EngineInfo::set_code_range( void* _pBase, ElfW(Phdr)* _pPhdr )
|
|
||||||
{
|
|
||||||
unsigned char* pBase = (unsigned char*)_pBase;
|
|
||||||
m_codeStart = pBase + _pPhdr->p_vaddr;
|
|
||||||
m_codeEnd = pBase + _pPhdr->p_vaddr + _pPhdr->p_memsz;
|
|
||||||
|
|
||||||
m_state = STATE_VALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
|
|
||||||
int DLLINTERNAL EngineInfo::initialise( enginefuncs_t* _pFuncs )
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
// Have to do this only once.
|
|
||||||
if ( NULL != m_codeStart ) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
|
|
||||||
ret = nthdr_module_name();
|
|
||||||
if ( MODULE_NAME_NOTFOUND == ret && (! _pFuncs->pfnIsDedicatedServer()) ) {
|
|
||||||
// We could not find the engine dll by name and we are running on
|
|
||||||
// a listen server. This usually means that that we are dealing with
|
|
||||||
// a VAC protected engine dll. No other way than approximating the
|
|
||||||
// range of valid engine function pointers in this case.
|
|
||||||
ret = vac_pe_approx( _pFuncs );
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* _WIN32 */
|
|
||||||
|
|
||||||
// If we have no reference pointer to start from we can only try to use
|
|
||||||
// the r_debug symbol.
|
|
||||||
if ( NULL == _pFuncs ) {
|
|
||||||
ret = phdr_r_debug();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have a refererence pointer we try to use it first.
|
|
||||||
if ( 0 != phdr_dladdr(_pFuncs) ) {
|
|
||||||
ret = phdr_r_debug();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
if ( 0 != ret ) {
|
|
||||||
META_DEV( "Unable to determine engine code address range!" );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
META_DEV( "Set engine code range: start address = %p, end address = %p",
|
|
||||||
m_codeStart, m_codeEnd );
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// autodetect.cpp - GameDLL search and autodetection.
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
|
||||||
*
|
|
||||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
#include "osdep_p.h" // is_gamedll, ...
|
|
||||||
#include "game_autodetect.h" // me
|
|
||||||
#include "support_meta.h" // full_gamedir_path,
|
|
||||||
|
|
||||||
|
|
||||||
// Search gamedir/dlls/*.dll for gamedlls
|
|
||||||
//TODO: add META_DEBUG
|
|
||||||
const char * DLLINTERNAL autodetect_gamedll(const gamedll_t *gamedll, const char *knownfn)
|
|
||||||
{
|
|
||||||
static char buf[256];
|
|
||||||
char dllpath[256];
|
|
||||||
char fnpath[256];
|
|
||||||
DIR *dir;
|
|
||||||
struct dirent *ent;
|
|
||||||
unsigned int fn_len;
|
|
||||||
|
|
||||||
// Generate dllpath
|
|
||||||
safevoid_snprintf(buf, sizeof(buf), "%s/dlls", gamedll->gamedir);
|
|
||||||
if(!full_gamedir_path(buf, dllpath)) {
|
|
||||||
//whine & return
|
|
||||||
META_WARNING("GameDLL-Autodetection: Directory '%s' doesn't exist.", buf);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate knownfn path
|
|
||||||
safevoid_snprintf(fnpath, sizeof(fnpath), "%s/%s", dllpath, knownfn);
|
|
||||||
|
|
||||||
// Check if knownfn exists and is valid gamedll
|
|
||||||
if(is_gamedll(fnpath)) {
|
|
||||||
// knownfn exists and is loadable gamedll, return 0.
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open directory
|
|
||||||
if(!(dir = opendir(dllpath))) {
|
|
||||||
//whine & return
|
|
||||||
META_WARNING("GameDLL-Autodetection: Couldn't open directory '%s'.", dllpath);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
while((ent = readdir(dir)) != 0) {
|
|
||||||
fn_len = strlen(ent->d_name);
|
|
||||||
|
|
||||||
if(fn_len <= strlen(PLATFORM_DLEXT)) {
|
|
||||||
// Filename is too short
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compare end of filename with PLATFORM_DLEXT
|
|
||||||
if(!strcasematch(&ent->d_name[fn_len - strlen(PLATFORM_DLEXT)], PLATFORM_DLEXT)) {
|
|
||||||
// File isn't dll
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exclude all metamods
|
|
||||||
if(strncasematch(ent->d_name, "metamod", strlen("metamod"))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Exclude all bots
|
|
||||||
STRNCPY(buf, ent->d_name, sizeof(buf));
|
|
||||||
strlwr(buf);
|
|
||||||
if(strstr(buf, "bot.")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#ifdef linux
|
|
||||||
//bot_iX86.so, bot_amd64.so, bot_x86_64.so
|
|
||||||
if(strstr(buf, "bot_i") || strstr(buf, "bot_amd64.so") || strstr(buf, "bot_x86")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Generate full path
|
|
||||||
safevoid_snprintf(fnpath, sizeof(fnpath), "%s/%s", dllpath, ent->d_name);
|
|
||||||
|
|
||||||
// Check if dll is gamedll
|
|
||||||
if(is_gamedll(fnpath)) {
|
|
||||||
META_DEBUG(8, ("is_gamedll(%s): ok.", fnpath));
|
|
||||||
//gamedll detected
|
|
||||||
STRNCPY(buf, ent->d_name, sizeof(buf));
|
|
||||||
closedir(dir);
|
|
||||||
return(buf);
|
|
||||||
}
|
|
||||||
META_DEBUG(8, ("is_gamedll(%s): failed.", fnpath));
|
|
||||||
}
|
|
||||||
|
|
||||||
//not found
|
|
||||||
META_WARNING("GameDLL-Autodetection: Couldn't find gamedll in '%s'.", dllpath);
|
|
||||||
closedir(dir);
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,331 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// game_support.cpp - info to recognize different HL mod "games"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2013 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#include <fcntl.h> // open, write
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "game_support.h" // me
|
|
||||||
#include "log_meta.h" // META_LOG, etc
|
|
||||||
#include "types_meta.h" // mBOOL
|
|
||||||
#include "osdep.h" // win32 snprintf, etc
|
|
||||||
#include "game_autodetect.h" // autodetect_gamedll
|
|
||||||
#include "support_meta.h" // MIN
|
|
||||||
|
|
||||||
// Adapted from adminmod h_export.cpp:
|
|
||||||
//! this structure contains a list of supported mods and their dlls names
|
|
||||||
//! To add support for another mod add an entry here, and add all the
|
|
||||||
//! exported entities to link_func.cpp
|
|
||||||
const game_modlist_t known_games = {
|
|
||||||
// name/gamedir linux_so win_dll desc
|
|
||||||
//
|
|
||||||
// Previously enumerated in this sourcefile, the list is now kept in a
|
|
||||||
// separate file, generated based on game information stored in a
|
|
||||||
// convenient db.
|
|
||||||
//
|
|
||||||
#include "games.h"
|
|
||||||
// End of list terminator:
|
|
||||||
{NULL, NULL, NULL, NULL}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Find a modinfo corresponding to the given game name.
|
|
||||||
const game_modinfo_t * DLLINTERNAL lookup_game(const char *name) {
|
|
||||||
const game_modinfo_t *imod;
|
|
||||||
int i;
|
|
||||||
for(i=0; known_games[i].name; i++) {
|
|
||||||
imod=&known_games[i];
|
|
||||||
if(strcasematch(imod->name, name))
|
|
||||||
return(imod);
|
|
||||||
}
|
|
||||||
// no match found
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Installs gamedll from Steam cache
|
|
||||||
mBOOL DLLINTERNAL install_gamedll(char *from, const char *to) {
|
|
||||||
int length_in;
|
|
||||||
int length_out;
|
|
||||||
|
|
||||||
if(!from)
|
|
||||||
return mFALSE;
|
|
||||||
if(!to)
|
|
||||||
to = from;
|
|
||||||
|
|
||||||
byte* cachefile = LOAD_FILE_FOR_ME(from, &length_in);
|
|
||||||
|
|
||||||
// If the file seems to exist in the cache.
|
|
||||||
if(cachefile) {
|
|
||||||
int fd=open(to, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
|
|
||||||
|
|
||||||
if(fd < 0) {
|
|
||||||
META_DEBUG(3, ("Installing gamedll from cache: Failed to create file %s: %s", to, strerror(errno)) );
|
|
||||||
FREE_FILE(cachefile);
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
length_out=write(fd, cachefile, length_in);
|
|
||||||
FREE_FILE(cachefile);
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
// Writing the file was not successfull
|
|
||||||
if(length_out != length_in) {
|
|
||||||
META_DEBUG(3,("Installing gamedll from chache: Failed to write all %d bytes to file, only %d written: %s", length_in, length_out, strerror(errno)));
|
|
||||||
// Let's not leave a mess but clean up nicely.
|
|
||||||
if(length_out >= 0)
|
|
||||||
unlink(to);
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
META_LOG("Installed gamedll %s from cache.", to);
|
|
||||||
} else {
|
|
||||||
META_DEBUG(3, ("Failed to install gamedll from cache: file %s not found in cache.", from) );
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set all the fields in the gamedll struct, - based either on an entry in
|
|
||||||
// known_games matching the current gamedir, or on one specified manually
|
|
||||||
// by the server admin.
|
|
||||||
//
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_NOTFOUND couldn't recognize game
|
|
||||||
mBOOL DLLINTERNAL setup_gamedll(gamedll_t *gamedll) {
|
|
||||||
#ifdef __x86_64__
|
|
||||||
static char fixname_amd64[NAME_MAX]; // pointer is given outside function
|
|
||||||
#endif
|
|
||||||
static char override_desc_buf[NAME_MAX]; // pointer is given outside function
|
|
||||||
static char autodetect_desc_buf[NAME_MAX]; // pointer is given outside function
|
|
||||||
char install_path[NAME_MAX];
|
|
||||||
const game_modinfo_t *known;
|
|
||||||
char *cp, *strippedfn;
|
|
||||||
const char *autofn = 0, *knownfn=0, *usedfn = 0;
|
|
||||||
int override=0;
|
|
||||||
|
|
||||||
// Check for old-style "metagame.ini" file and complain.
|
|
||||||
if(valid_gamedir_file(OLD_GAMEDLL_TXT))
|
|
||||||
META_WARNING("File '%s' is no longer supported; instead, specify override gamedll in %s or with '+localinfo mm_gamedll <dllfile>'", OLD_GAMEDLL_TXT, CONFIG_INI);
|
|
||||||
// First, look for a known game, based on gamedir.
|
|
||||||
if((known=lookup_game(gamedll->name))) {
|
|
||||||
#ifdef _WIN32
|
|
||||||
knownfn=known->win_dll;
|
|
||||||
#elif defined(linux)
|
|
||||||
knownfn=known->linux_so;
|
|
||||||
#ifdef __x86_64__
|
|
||||||
//AMD64: convert _i386.so to _amd64.so
|
|
||||||
if((cp = strstr(knownfn, "_i386.so")) ||
|
|
||||||
(cp = strstr(knownfn, "_i486.so")) ||
|
|
||||||
(cp = strstr(knownfn, "_i586.so")) ||
|
|
||||||
(cp = strstr(knownfn, "_i686.so"))) {
|
|
||||||
//make sure that it's the ending that has "_iX86.so"
|
|
||||||
if(cp[strlen("_i386.so")] == 0) {
|
|
||||||
STRNCPY(fixname_amd64, known->linux_so,
|
|
||||||
MIN(((size_t)cp - (size_t)knownfn) + 1,
|
|
||||||
sizeof(fixname_amd64)));
|
|
||||||
strncat(fixname_amd64, "_amd64.so", sizeof(fixname_amd64));
|
|
||||||
|
|
||||||
knownfn=fixname_amd64;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /*__x86_64__*/
|
|
||||||
#else
|
|
||||||
#error "OS unrecognized"
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
// Do this before autodetecting gamedll from "dlls/*.dll"
|
|
||||||
if(!Config->gamedll) {
|
|
||||||
#ifdef linux
|
|
||||||
// The engine changed game dll lookup behaviour in that it strips
|
|
||||||
// anything after the last '_' from the name and tries to load the
|
|
||||||
// resulting name. The DSO names were changed and do not have the
|
|
||||||
// '_i386' part in them anymore, so cs_i386.so became cs.so. We
|
|
||||||
// have to adapt to that and try to load the DSO name without the
|
|
||||||
// '_*' part first, to see if we have a new version file available.
|
|
||||||
char temp_str[NAME_MAX];
|
|
||||||
|
|
||||||
STRNCPY(temp_str, knownfn, sizeof(temp_str));
|
|
||||||
strippedfn = temp_str;
|
|
||||||
|
|
||||||
char *loc = strrchr(strippedfn, '_');
|
|
||||||
|
|
||||||
// A small safety net here: make sure that we are dealing with
|
|
||||||
// a file name at least four characters long and ending in
|
|
||||||
// '.so'. This way we can be sure that we can safely overwrite
|
|
||||||
// anything from the '_' on with '.so'.
|
|
||||||
int size = 0;
|
|
||||||
const char *ext;
|
|
||||||
if(0 != loc) {
|
|
||||||
size = strlen(strippedfn);
|
|
||||||
ext = strippedfn + (size - 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(0 != loc && size > 3 && 0 == strcasecmp(ext, ".so")) {
|
|
||||||
strcpy(loc, ".so");
|
|
||||||
META_DEBUG(4, ("Checking for new version game DLL name '%s'.\n", strippedfn) );
|
|
||||||
|
|
||||||
// Again, as above, I abuse the real_pathname member to store the full pathname
|
|
||||||
// and the pathname member to store the relative name to pass it to the
|
|
||||||
// install_gamedll function to save stack space. They are going
|
|
||||||
// to get overwritten later on, so that's ok.
|
|
||||||
safevoid_snprintf(gamedll->pathname, sizeof(gamedll->pathname), "dlls/%s",
|
|
||||||
strippedfn);
|
|
||||||
// Check if the gamedll file exists. If not, try to install it from
|
|
||||||
// the cache.
|
|
||||||
mBOOL ok = mTRUE;
|
|
||||||
if(!valid_gamedir_file(gamedll->pathname)) {
|
|
||||||
safevoid_snprintf(gamedll->real_pathname, sizeof(gamedll->real_pathname), "%s/dlls/%s",
|
|
||||||
gamedll->gamedir, strippedfn);
|
|
||||||
ok = install_gamedll(gamedll->pathname, gamedll->real_pathname);
|
|
||||||
}
|
|
||||||
if(ok)
|
|
||||||
usedfn = strippedfn;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
META_DEBUG(4, ("Known game DLL name does not qualify for checking for a stripped version, skipping: '%s'.\n",
|
|
||||||
strippedfn) );
|
|
||||||
}
|
|
||||||
#endif /* linux */
|
|
||||||
// If no file to be used was found, try the old known DLL file
|
|
||||||
// name.
|
|
||||||
if (0 == usedfn) {
|
|
||||||
META_DEBUG(4, ("Checking for old version game DLL name '%s'.\n", knownfn) );
|
|
||||||
safevoid_snprintf(gamedll->pathname, sizeof(gamedll->pathname), "dlls/%s", knownfn);
|
|
||||||
// Check if the gamedll file exists. If not, try to install it from
|
|
||||||
// the cache.
|
|
||||||
if(!valid_gamedir_file(gamedll->pathname)) {
|
|
||||||
safevoid_snprintf(gamedll->real_pathname, sizeof(gamedll->real_pathname), "%s/dlls/%s",
|
|
||||||
gamedll->gamedir, knownfn);
|
|
||||||
install_gamedll(gamedll->pathname, gamedll->real_pathname);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
knownfn = usedfn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then, autodetect gamedlls in "gamedir/dlls/"
|
|
||||||
// autodetect_gamedll returns 0 if knownfn exists and is valid gamedll.
|
|
||||||
if(Config->autodetect && (autofn=autodetect_gamedll(gamedll, knownfn))) {
|
|
||||||
// If knownfn is set and autodetect_gamedll returns non-null
|
|
||||||
// then knownfn doesn't exists and we should use autodetected
|
|
||||||
// dll instead.
|
|
||||||
if(knownfn) {
|
|
||||||
// Whine loud about fact that known-list dll doesn't exists!
|
|
||||||
//META_LOG(plapla);
|
|
||||||
knownfn = autofn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Neither override nor known-list nor auto-detect found a gamedll.
|
|
||||||
if(!known && !Config->gamedll && !autofn)
|
|
||||||
RETURN_ERRNO(mFALSE, ME_NOTFOUND);
|
|
||||||
|
|
||||||
// Use override-dll if specified.
|
|
||||||
if(Config->gamedll) {
|
|
||||||
STRNCPY(gamedll->pathname, Config->gamedll,
|
|
||||||
sizeof(gamedll->pathname));
|
|
||||||
override=1;
|
|
||||||
|
|
||||||
// If the path is relative, the gamedll file will be missing and
|
|
||||||
// it might be found in the cache file.
|
|
||||||
if(!is_absolute_path(gamedll->pathname)) {
|
|
||||||
safevoid_snprintf(install_path, sizeof(install_path),
|
|
||||||
"%s/%s", gamedll->gamedir, gamedll->pathname);
|
|
||||||
// If we could successfully install the gamedll from the cache we
|
|
||||||
// rectify the pathname to be a full pathname.
|
|
||||||
if(install_gamedll(gamedll->pathname, install_path))
|
|
||||||
STRNCPY(gamedll->pathname, install_path, sizeof(gamedll->pathname));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Else use Known-list dll.
|
|
||||||
else if(known) {
|
|
||||||
safevoid_snprintf(gamedll->pathname, sizeof(gamedll->pathname), "%s/dlls/%s",
|
|
||||||
gamedll->gamedir, knownfn);
|
|
||||||
}
|
|
||||||
// Else use Autodetect dll.
|
|
||||||
else {
|
|
||||||
safevoid_snprintf(gamedll->pathname, sizeof(gamedll->pathname), "%s/dlls/%s",
|
|
||||||
gamedll->gamedir, autofn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get filename from pathname
|
|
||||||
cp=strrchr(gamedll->pathname, '/');
|
|
||||||
if(cp)
|
|
||||||
cp++;
|
|
||||||
else
|
|
||||||
cp=gamedll->pathname;
|
|
||||||
gamedll->file=cp;
|
|
||||||
|
|
||||||
// If found, store also the supposed "real" dll path based on the
|
|
||||||
// gamedir, in case it differs from the "override" dll path.
|
|
||||||
if(known && override)
|
|
||||||
safevoid_snprintf(gamedll->real_pathname, sizeof(gamedll->real_pathname),
|
|
||||||
"%s/dlls/%s", gamedll->gamedir, knownfn);
|
|
||||||
else if(known && autofn)
|
|
||||||
safevoid_snprintf(gamedll->real_pathname, sizeof(gamedll->real_pathname),
|
|
||||||
"%s/dlls/%s", gamedll->gamedir, knownfn);
|
|
||||||
else // !known or (!override and !autofn)
|
|
||||||
STRNCPY(gamedll->real_pathname, gamedll->pathname,
|
|
||||||
sizeof(gamedll->real_pathname));
|
|
||||||
|
|
||||||
if(override) {
|
|
||||||
// generate a desc
|
|
||||||
safevoid_snprintf(override_desc_buf, sizeof(override_desc_buf), "%s (override)", gamedll->file);
|
|
||||||
gamedll->desc=override_desc_buf;
|
|
||||||
// log result
|
|
||||||
META_LOG("Overriding game '%s' with dllfile '%s'", gamedll->name, gamedll->file);
|
|
||||||
}
|
|
||||||
else if(known && autofn) {
|
|
||||||
// dll in known-list doesn't exists but we found new one with autodetect.
|
|
||||||
|
|
||||||
// generate a desc
|
|
||||||
safevoid_snprintf(autodetect_desc_buf, sizeof(autodetect_desc_buf), "%s (autodetect-override)", gamedll->file);
|
|
||||||
gamedll->desc=autodetect_desc_buf;
|
|
||||||
META_LOG("Recognized game '%s'; Autodetection override; using dllfile '%s'", gamedll->name, gamedll->file);
|
|
||||||
}
|
|
||||||
else if(autofn) {
|
|
||||||
// generate a desc
|
|
||||||
safevoid_snprintf(autodetect_desc_buf, sizeof(autodetect_desc_buf), "%s (autodetect)", gamedll->file);
|
|
||||||
gamedll->desc=autodetect_desc_buf;
|
|
||||||
META_LOG("Autodetected game '%s'; using dllfile '%s'", gamedll->name, gamedll->file);
|
|
||||||
}
|
|
||||||
else if(known) {
|
|
||||||
gamedll->desc=known->desc;
|
|
||||||
META_LOG("Recognized game '%s'; using dllfile '%s'", gamedll->name, gamedll->file);
|
|
||||||
}
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// h_export.cpp - main exported DLL functionality
|
|
||||||
|
|
||||||
// From SDK dlls/h_export.cpp:
|
|
||||||
|
|
||||||
/***
|
|
||||||
*
|
|
||||||
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
|
|
||||||
*
|
|
||||||
* This product contains software technology licensed from Id
|
|
||||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
|
||||||
* All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use, distribution, and modification of this source code and/or resulting
|
|
||||||
* object code is restricted to non-commercial enhancements to products from
|
|
||||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
|
||||||
* without written permission from Valve LLC.
|
|
||||||
*
|
|
||||||
****/
|
|
||||||
/*
|
|
||||||
|
|
||||||
===== h_export.cpp ========================================================
|
|
||||||
|
|
||||||
Entity classes exported by Halflife.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "h_export.h" // me
|
|
||||||
#include "metamod.h" // engine_t, etc
|
|
||||||
#include "log_meta.h" // META_DEV, etc
|
|
||||||
#include "osdep_p.h" // get_module_handle_of_memptr
|
|
||||||
|
|
||||||
// From SDK dlls/h_export.cpp:
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
//! Required DLL entry point
|
|
||||||
// The above SDK comment indicates this routine is required, but the MSDN
|
|
||||||
// documentation indicates it's actually optional. We keep it, though, for
|
|
||||||
// completeness.
|
|
||||||
// Note! 'extern "C"' needed for mingw compile.
|
|
||||||
extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|
||||||
{
|
|
||||||
if (fdwReason == DLL_PROCESS_ATTACH) {
|
|
||||||
metamod_handle = hinstDLL;
|
|
||||||
}
|
|
||||||
else if (fdwReason == DLL_PROCESS_DETACH) {
|
|
||||||
/* nothing */
|
|
||||||
}
|
|
||||||
return(TRUE);
|
|
||||||
}
|
|
||||||
#elif defined(linux)
|
|
||||||
// Linux routines to correspond to ATTACH and DETACH cases above. These
|
|
||||||
// aren't required by linux, but are included here for completeness, and
|
|
||||||
// just in case we come across a need to do something at dll load or
|
|
||||||
// unload.
|
|
||||||
void _init(void) {
|
|
||||||
// called before dlopen() returns
|
|
||||||
}
|
|
||||||
void _fini(void) {
|
|
||||||
// called before dlclose() returns
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Fixed MSVC compiling, by Nikolay "The Storm" Baklicharov.
|
|
||||||
#if defined(_WIN32) && !defined(__GNUC__) && defined (_MSC_VER)
|
|
||||||
#pragma comment(linker, "/EXPORT:GiveFnptrsToDll=_GiveFnptrsToDll@8,@1")
|
|
||||||
#pragma comment(linker, "/SECTION:.data,RW")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//! Holds engine functionality callbacks
|
|
||||||
HL_enginefuncs_t g_engfuncs;
|
|
||||||
globalvars_t *gpGlobals;
|
|
||||||
engine_t Engine;
|
|
||||||
|
|
||||||
// Receive engine function table from engine.
|
|
||||||
//
|
|
||||||
// This appears to be the _first_ DLL routine called by the engine, so this
|
|
||||||
// is where we hook to load all the other DLLs (game, plugins, etc), which
|
|
||||||
// is actually all done in meta_startup().
|
|
||||||
C_DLLEXPORT void WINAPI GiveFnptrsToDll(enginefuncs_t *pengfuncsFromEngine,
|
|
||||||
globalvars_t *pGlobals)
|
|
||||||
{
|
|
||||||
#ifdef linux
|
|
||||||
metamod_handle = get_module_handle_of_memptr((void*)&g_engfuncs);
|
|
||||||
#endif
|
|
||||||
gpGlobals = pGlobals;
|
|
||||||
Engine.funcs = &g_engfuncs;
|
|
||||||
Engine.globals = pGlobals;
|
|
||||||
Engine.info.initialise(pengfuncsFromEngine);
|
|
||||||
|
|
||||||
g_engfuncs.initialise_interface(pengfuncsFromEngine);
|
|
||||||
// NOTE! Have to call logging function _after_ initialising g_engfuncs, so
|
|
||||||
// that g_engfuncs.pfnAlertMessage() can be resolved properly, heh. :)
|
|
||||||
META_DEV("called: GiveFnptrsToDll");
|
|
||||||
|
|
||||||
// Load plugins, load game dll.
|
|
||||||
if(!metamod_startup()) {
|
|
||||||
metamod_not_loaded = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
@@ -1,205 +0,0 @@
|
|||||||
/* Special ld script needed, because HL engine does some PE section checking on loaded gamedlls. */
|
|
||||||
/* These checks fail and segfault HL process if default ld script is used! */
|
|
||||||
OUTPUT_FORMAT(pei-i386)
|
|
||||||
SEARCH_DIR("/mingw/mingw32/lib"); SEARCH_DIR("/mingw/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
|
|
||||||
ENTRY(_mainCRTStartup)
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
.text __image_base__ + __section_alignment__ :
|
|
||||||
{
|
|
||||||
*(.init)
|
|
||||||
*(.text)
|
|
||||||
*(SORT(.text$*))
|
|
||||||
*(.glue_7t)
|
|
||||||
*(.glue_7)
|
|
||||||
___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
|
|
||||||
LONG (-1);
|
|
||||||
*(EXCLUDE_FILE (*crtend.o) .ctors);
|
|
||||||
*(.ctor);
|
|
||||||
*(SORT(.ctors.*));
|
|
||||||
*crtend.o (.ctors);
|
|
||||||
LONG (0);
|
|
||||||
___DTOR_LIST__ = .; __DTOR_LIST__ = . ;
|
|
||||||
LONG (-1);
|
|
||||||
*(EXCLUDE_FILE (*crtend.o) .dtors);
|
|
||||||
*(.dtor);
|
|
||||||
*(SORT(.dtors.*));
|
|
||||||
*crtend.o (.dtors);
|
|
||||||
LONG (0);
|
|
||||||
*(.fini)
|
|
||||||
/* ??? Why is .gcc_exc here? */
|
|
||||||
*(.gcc_exc)
|
|
||||||
PROVIDE (etext = .);
|
|
||||||
*(.gcc_except_table)
|
|
||||||
/*}
|
|
||||||
.rdata BLOCK(__section_alignment__) :
|
|
||||||
{*/
|
|
||||||
*(.rdata)
|
|
||||||
*(SORT(.rdata$*))
|
|
||||||
}
|
|
||||||
/* The Cygwin32 library uses a section to avoid copying certain data
|
|
||||||
on fork. This used to be named ".data". The linker used
|
|
||||||
to include this between __data_start__ and __data_end__, but that
|
|
||||||
breaks building the cygwin32 dll. Instead, we name the section
|
|
||||||
".data_cygwin_nocopy" and explictly include it after __data_end__. */
|
|
||||||
.data BLOCK(__section_alignment__) :
|
|
||||||
{
|
|
||||||
__data_start__ = . ;
|
|
||||||
*(.data)
|
|
||||||
*(.data2)
|
|
||||||
*(SORT(.data$*))
|
|
||||||
__data_end__ = . ;
|
|
||||||
*(.data_cygwin_nocopy)
|
|
||||||
*(.eh_frame)
|
|
||||||
___RUNTIME_PSEUDO_RELOC_LIST__ = .;
|
|
||||||
__RUNTIME_PSEUDO_RELOC_LIST__ = .;
|
|
||||||
*(.rdata_runtime_pseudo_reloc)
|
|
||||||
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
|
||||||
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
|
||||||
/*}
|
|
||||||
.bss BLOCK(__section_alignment__) :
|
|
||||||
{*/
|
|
||||||
__bss_start__ = . ;
|
|
||||||
*(.bss)
|
|
||||||
*(COMMON)
|
|
||||||
__bss_end__ = . ;
|
|
||||||
}
|
|
||||||
.edata BLOCK(__section_alignment__) :
|
|
||||||
{
|
|
||||||
*(.edata)
|
|
||||||
}
|
|
||||||
.idata BLOCK(__section_alignment__) :
|
|
||||||
{
|
|
||||||
/* This cannot currently be handled with grouped sections.
|
|
||||||
See pe.em:sort_sections. */
|
|
||||||
SORT(*)(.idata$2)
|
|
||||||
SORT(*)(.idata$3)
|
|
||||||
/* These zeroes mark the end of the import list. */
|
|
||||||
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
|
|
||||||
SORT(*)(.idata$4)
|
|
||||||
SORT(*)(.idata$5)
|
|
||||||
SORT(*)(.idata$6)
|
|
||||||
SORT(*)(.idata$7)
|
|
||||||
}
|
|
||||||
/DISCARD/ :
|
|
||||||
{
|
|
||||||
*(.debug$S)
|
|
||||||
*(.debug$T)
|
|
||||||
*(.debug$F)
|
|
||||||
*(.drectve)
|
|
||||||
}
|
|
||||||
.CRT BLOCK(__section_alignment__) :
|
|
||||||
{
|
|
||||||
___crt_xc_start__ = . ;
|
|
||||||
*(SORT(.CRT$XC*)) /* C initialization */
|
|
||||||
___crt_xc_end__ = . ;
|
|
||||||
___crt_xi_start__ = . ;
|
|
||||||
*(SORT(.CRT$XI*)) /* C++ initialization */
|
|
||||||
___crt_xi_end__ = . ;
|
|
||||||
___crt_xl_start__ = . ;
|
|
||||||
*(SORT(.CRT$XL*)) /* TLS callbacks */
|
|
||||||
/* ___crt_xl_end__ is defined in the TLS Directory support code */
|
|
||||||
___crt_xp_start__ = . ;
|
|
||||||
*(SORT(.CRT$XP*)) /* Pre-termination */
|
|
||||||
___crt_xp_end__ = . ;
|
|
||||||
___crt_xt_start__ = . ;
|
|
||||||
*(SORT(.CRT$XT*)) /* Termination */
|
|
||||||
___crt_xt_end__ = . ;
|
|
||||||
}
|
|
||||||
.tls BLOCK(__section_alignment__) :
|
|
||||||
{
|
|
||||||
___tls_start__ = . ;
|
|
||||||
*(.tls)
|
|
||||||
*(.tls$)
|
|
||||||
*(SORT(.tls$*))
|
|
||||||
___tls_end__ = . ;
|
|
||||||
}
|
|
||||||
.endjunk BLOCK(__section_alignment__) :
|
|
||||||
{
|
|
||||||
/* end is deprecated, don't use it */
|
|
||||||
PROVIDE (end = .);
|
|
||||||
PROVIDE ( _end = .);
|
|
||||||
__end__ = .;
|
|
||||||
}
|
|
||||||
.rsrc BLOCK(__section_alignment__) :
|
|
||||||
{
|
|
||||||
*(.rsrc)
|
|
||||||
*(SORT(.rsrc$*))
|
|
||||||
}
|
|
||||||
.reloc BLOCK(__section_alignment__) :
|
|
||||||
{
|
|
||||||
*(.reloc)
|
|
||||||
}
|
|
||||||
.stab BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.stab)
|
|
||||||
}
|
|
||||||
.stabstr BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.stabstr)
|
|
||||||
}
|
|
||||||
/* DWARF debug sections.
|
|
||||||
Symbols in the DWARF debugging sections are relative to the beginning
|
|
||||||
of the section. Unlike other targets that fake this by putting the
|
|
||||||
section VMA at 0, the PE format will not allow it. */
|
|
||||||
/* DWARF 1.1 and DWARF 2. */
|
|
||||||
.debug_aranges BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_aranges)
|
|
||||||
}
|
|
||||||
.debug_pubnames BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_pubnames)
|
|
||||||
}
|
|
||||||
/* DWARF 2. */
|
|
||||||
.debug_info BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_info) *(.gnu.linkonce.wi.*)
|
|
||||||
}
|
|
||||||
.debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_abbrev)
|
|
||||||
}
|
|
||||||
.debug_line BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_line)
|
|
||||||
}
|
|
||||||
.debug_frame BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_frame)
|
|
||||||
}
|
|
||||||
.debug_str BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_str)
|
|
||||||
}
|
|
||||||
.debug_loc BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_loc)
|
|
||||||
}
|
|
||||||
.debug_macinfo BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_macinfo)
|
|
||||||
}
|
|
||||||
/* SGI/MIPS DWARF 2 extensions. */
|
|
||||||
.debug_weaknames BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_weaknames)
|
|
||||||
}
|
|
||||||
.debug_funcnames BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_funcnames)
|
|
||||||
}
|
|
||||||
.debug_typenames BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_typenames)
|
|
||||||
}
|
|
||||||
.debug_varnames BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_varnames)
|
|
||||||
}
|
|
||||||
/* DWARF 3. */
|
|
||||||
.debug_ranges BLOCK(__section_alignment__) (NOLOAD) :
|
|
||||||
{
|
|
||||||
*(.debug_ranges)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// linkgame.cpp - export entities from mod "games" back to the HL engine
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
//linkents not needed on this version of metamod
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// linkplug.cpp - export entities from plugins back to the HL engine
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "linkent.h" // LINK_ENTITY_TO_PLUGIN
|
|
||||||
|
|
||||||
// Entity lists for plugins
|
|
||||||
LINK_ENTITY_TO_PLUGIN(adminmod_timer, "adminmod");
|
|
||||||
@@ -1,240 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// log_mega.cpp - logging routines
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h> // vsnprintf, etc
|
|
||||||
#include <stdarg.h> // va_start, etc
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
#include "enginecallbacks.h" // ALERT, etc
|
|
||||||
|
|
||||||
#include "sdk_util.h" // SERVER_PRINT, etc
|
|
||||||
#include "log_meta.h" // me
|
|
||||||
#include "osdep.h" // win32 vsnprintf, etc
|
|
||||||
#include "support_meta.h" // MAX
|
|
||||||
|
|
||||||
cvar_t meta_debug = {"meta_debug", "0", FCVAR_EXTDLL, 0, NULL};
|
|
||||||
|
|
||||||
int meta_debug_value = 0; //meta_debug_value is converted from float(meta_debug.value) to int on every frame
|
|
||||||
|
|
||||||
enum MLOG_SERVICE {
|
|
||||||
mlsCONS = 1,
|
|
||||||
mlsDEV,
|
|
||||||
mlsIWEL,
|
|
||||||
mlsCLIENT
|
|
||||||
};
|
|
||||||
|
|
||||||
static void buffered_ALERT(MLOG_SERVICE service, ALERT_TYPE atype, const char *prefix, const char *fmt, va_list ap);
|
|
||||||
|
|
||||||
// Print to console.
|
|
||||||
void DLLINTERNAL META_CONS(const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
char buf[MAX_LOGMSG_LEN];
|
|
||||||
unsigned int len;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
len=strlen(buf);
|
|
||||||
if(len < sizeof(buf)-2) { // -1 null, -1 for newline
|
|
||||||
buf[len+0] = '\n';
|
|
||||||
buf[len+1] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
buf[len-1] = '\n';
|
|
||||||
|
|
||||||
SERVER_PRINT(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log developer-level messages (obsoleted).
|
|
||||||
static const char *const prefixDEV = "[META] dev:";
|
|
||||||
void DLLINTERNAL META_DEV(const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
int dev;
|
|
||||||
|
|
||||||
if(NULL != g_engfuncs.pfnCVarGetFloat) {
|
|
||||||
dev=(int) CVAR_GET_FLOAT("developer");
|
|
||||||
if(dev==0) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
buffered_ALERT(mlsDEV, at_logged, prefixDEV, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log infos.
|
|
||||||
static const char *const prefixINFO = "[META] INFO:";
|
|
||||||
void DLLINTERNAL META_INFO(const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
buffered_ALERT(mlsIWEL, at_logged, prefixINFO, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log warnings.
|
|
||||||
static const char *const prefixWARNING = "[META] WARNING:";
|
|
||||||
void DLLINTERNAL META_WARNING(const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
buffered_ALERT(mlsIWEL, at_logged, prefixWARNING, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log errors.
|
|
||||||
static const char *const prefixERROR = "[META] ERROR:";
|
|
||||||
void DLLINTERNAL META_ERROR(const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
buffered_ALERT(mlsIWEL, at_logged, prefixERROR, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normal log messages.
|
|
||||||
static const char *const prefixLOG = "[META]";
|
|
||||||
void DLLINTERNAL META_LOG(const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
buffered_ALERT(mlsIWEL, at_logged, prefixLOG, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print to client.
|
|
||||||
void DLLINTERNAL META_CLIENT(edict_t *pEntity, const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
char buf[MAX_CLIENTMSG_LEN];
|
|
||||||
unsigned int len;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
len=strlen(buf);
|
|
||||||
if(len < sizeof(buf)-2) { // -1 null, -1 for newline
|
|
||||||
buf[len+0] = '\n';
|
|
||||||
buf[len+1] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
buf[len-1] = '\n';
|
|
||||||
|
|
||||||
CLIENT_PRINTF(pEntity, print_console, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef __BUILD_FAST_METAMOD__
|
|
||||||
|
|
||||||
static int debug_level;
|
|
||||||
|
|
||||||
void DLLINTERNAL META_DEBUG_SET_LEVEL(int level) {
|
|
||||||
debug_level = level;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DLLINTERNAL META_DO_DEBUG(const char *fmt, ...) {
|
|
||||||
char meta_debug_str[1024];
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
safevoid_vsnprintf(meta_debug_str, sizeof(meta_debug_str), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
ALERT(at_logged, "[META] (debug:%d) %s\n", debug_level, meta_debug_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /*!__BUILD_FAST_METAMOD__*/
|
|
||||||
|
|
||||||
class BufferedMessage : public class_metamod_new {
|
|
||||||
public:
|
|
||||||
MLOG_SERVICE service;
|
|
||||||
ALERT_TYPE atype;
|
|
||||||
const char *prefix;
|
|
||||||
char buf[MAX_LOGMSG_LEN];
|
|
||||||
BufferedMessage *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
static BufferedMessage *messageQueueStart = NULL;
|
|
||||||
static BufferedMessage *messageQueueEnd = NULL;
|
|
||||||
|
|
||||||
static void buffered_ALERT(MLOG_SERVICE service, ALERT_TYPE atype, const char *prefix, const char *fmt, va_list ap) {
|
|
||||||
char buf[MAX_LOGMSG_LEN];
|
|
||||||
BufferedMessage *msg;
|
|
||||||
|
|
||||||
if (NULL != g_engfuncs.pfnAlertMessage) {
|
|
||||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
||||||
ALERT(atype, "%s %s\n", prefix, buf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Engine AlertMessage function not available. Buffer message.
|
|
||||||
msg = new BufferedMessage;
|
|
||||||
if (NULL == msg) {
|
|
||||||
// though luck, gonna lose this message
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
msg->service = service;
|
|
||||||
msg->atype = atype;
|
|
||||||
msg->prefix = prefix;
|
|
||||||
vsnprintf(msg->buf, sizeof(buf), fmt, ap);
|
|
||||||
msg->next = NULL;
|
|
||||||
|
|
||||||
if (NULL == messageQueueEnd) {
|
|
||||||
messageQueueStart = messageQueueEnd = msg;
|
|
||||||
} else {
|
|
||||||
messageQueueEnd->next = msg;
|
|
||||||
messageQueueEnd = msg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Flushes the message queue, printing messages to the respective
|
|
||||||
// service. This function doesn't check anymore if the g_engfuncs
|
|
||||||
// jumptable is set. Don't call it if it isn't set.
|
|
||||||
void DLLINTERNAL flush_ALERT_buffer(void) {
|
|
||||||
BufferedMessage *msg = messageQueueStart;
|
|
||||||
int dev = (int) CVAR_GET_FLOAT("developer");
|
|
||||||
|
|
||||||
while (NULL != msg) {
|
|
||||||
if(msg->service == mlsDEV && dev==0) {
|
|
||||||
;
|
|
||||||
} else {
|
|
||||||
ALERT(msg->atype, "b>%s %s\n", msg->prefix, msg->buf);
|
|
||||||
}
|
|
||||||
messageQueueStart = messageQueueStart->next;
|
|
||||||
delete msg;
|
|
||||||
msg = messageQueueStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
messageQueueStart = messageQueueEnd = NULL;
|
|
||||||
}
|
|
||||||
@@ -1,724 +0,0 @@
|
|||||||
|
|
||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// meta_eiface.cpp - wrapper for engine/dll interface
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include <stdio.h> // fprintf()
|
|
||||||
#include <stdlib.h> // exit()
|
|
||||||
#include <string.h> // memset(), memcpy()
|
|
||||||
|
|
||||||
#include "meta_eiface.h" // me
|
|
||||||
#include "dllapi.h" // FN_CVARVALUE, FN_CVARVALUE2
|
|
||||||
#include "engine_t.h" // Engine
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// meta_new_dll_functions_t
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// static member initialisation
|
|
||||||
int meta_new_dll_functions_t::sm_version DLLHIDDEN = 0;
|
|
||||||
|
|
||||||
|
|
||||||
meta_new_dll_functions_t::meta_new_dll_functions_t(
|
|
||||||
void (*_pfnOnFreeEntPrivateData) (edict_t*),
|
|
||||||
void (*_pfnGameShutdown) (void),
|
|
||||||
int (*_pfnShouldCollide) (edict_t*, edict_t*),
|
|
||||||
void (*_pfnCvarValue) (const edict_t*, const char*),
|
|
||||||
void (*_pfnCvarValue2) (const edict_t*, int, const char*, const char*)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
pfnOnFreeEntPrivateData = _pfnOnFreeEntPrivateData;
|
|
||||||
pfnGameShutdown = _pfnGameShutdown;
|
|
||||||
pfnShouldCollide = _pfnShouldCollide;
|
|
||||||
pfnCvarValue = _pfnCvarValue;
|
|
||||||
pfnCvarValue2 = _pfnCvarValue2;
|
|
||||||
|
|
||||||
memset( dummies, 0, sizeof(pdummyfunc) * c_NumDummies );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void DLLINTERNAL meta_new_dll_functions_t::copy_to( NEW_DLL_FUNCTIONS *_pFuncs )
|
|
||||||
{
|
|
||||||
// This is where the magic happens. We check what version of the
|
|
||||||
// NEW_DLL_FUNCTIONS interface the engine has and calculate the size of
|
|
||||||
// that interface. Then we only copy the function pointers present in
|
|
||||||
// that version over to the receiver, so that we do not overwrite his
|
|
||||||
// memory with functions that he doesn't know of in his copy of the
|
|
||||||
// struct.
|
|
||||||
size_t size = get_size();
|
|
||||||
|
|
||||||
if ( 0 == size ) {
|
|
||||||
// Ok, this is a real problem and should *not* happen.
|
|
||||||
// We try to work with NEW_DLL_FUNCTIONS without knowing what
|
|
||||||
// interface the attached engine uses. This means that the classes
|
|
||||||
// defined herein are not used in the way they are meant to because
|
|
||||||
// someone forgot to first create a HL_enginefuncs_t object and
|
|
||||||
// initialise it with the pointers passed from the engine.
|
|
||||||
// We treat this as a major developer error and bluntly exit the
|
|
||||||
// whole process, assuming that this will never happen on a
|
|
||||||
// production server as it should have been caught by the developer
|
|
||||||
// during testing.
|
|
||||||
//
|
|
||||||
// We use a printf() to complain since we do not know if we have
|
|
||||||
// already attached to the engine and can use its alerting
|
|
||||||
// functions. This should be augemnted with a windows version
|
|
||||||
// popping open a message box.
|
|
||||||
fprintf( stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
|
|
||||||
fprintf( stderr, "ERROR: INTERNAL ERROR.\n" );
|
|
||||||
fprintf( stderr, " Attempt to use meta_new_dll_functions_t without initialised engine interface version!\n" );
|
|
||||||
fprintf( stderr, " %s at %d\n", __FILE__, __LINE__ );
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy( _pFuncs, this, size );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int DLLINTERNAL meta_new_dll_functions_t::determine_interface_version( void )
|
|
||||||
{
|
|
||||||
// If the meta_enginefuncs_t::version is 0, i.e. has not yet been
|
|
||||||
// determined, that is a problem and an error. We should probably throw
|
|
||||||
// a fit here or something.
|
|
||||||
// For now we just return 0 and leave it to the caller to complain.
|
|
||||||
if (meta_enginefuncs_t::version() == 0) return 0;
|
|
||||||
|
|
||||||
// The default version is 1.
|
|
||||||
sm_version = 1;
|
|
||||||
|
|
||||||
// With the enginefuncs interface version 156 the function
|
|
||||||
// pfnCvarValue() was added, which we call version 2.
|
|
||||||
if (meta_enginefuncs_t::version() >= 156) sm_version = 2;
|
|
||||||
|
|
||||||
// With the enginefuncs interface version 157 the function
|
|
||||||
// pfnCvarValue2() was added, which we call version 3.
|
|
||||||
if (meta_enginefuncs_t::version() >= 157) sm_version = 3;
|
|
||||||
|
|
||||||
return sm_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t DLLINTERNAL meta_new_dll_functions_t::get_size( int _version )
|
|
||||||
{
|
|
||||||
size_t size = sizeof(NEW_DLL_FUNCTIONS);
|
|
||||||
|
|
||||||
if ( 0 == _version ) {
|
|
||||||
// Use the current engine's interface version
|
|
||||||
_version = version();
|
|
||||||
|
|
||||||
// Error: meta_enginefuncs_t::version probably not yet set up.
|
|
||||||
if ( 0 == _version ) return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch( _version ) {
|
|
||||||
case 1:
|
|
||||||
// Version 1 is missing all functions from CvarValue() on.
|
|
||||||
size -= sizeof(FN_CVARVALUE);
|
|
||||||
case 2:
|
|
||||||
// Version 2 is missing all functions from CvarValue2() on.
|
|
||||||
size -= sizeof(FN_CVARVALUE2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------
|
|
||||||
// meta_enginefuncs_t
|
|
||||||
// --------------------------------------------------------------
|
|
||||||
|
|
||||||
// static member initialisation
|
|
||||||
int meta_enginefuncs_t::sm_version = 0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
meta_enginefuncs_t::meta_enginefuncs_t(
|
|
||||||
int (*_pfnPrecacheModel) (char*),
|
|
||||||
int (*_pfnPrecacheSound) (char*),
|
|
||||||
void (*_pfnSetModel) (edict_t*, const char*),
|
|
||||||
int (*_pfnModelIndex) (const char*),
|
|
||||||
int (*_pfnModelFrames) (int),
|
|
||||||
void (*_pfnSetSize) (edict_t*, const float*, const float*),
|
|
||||||
void (*_pfnChangeLevel) (char*, char*),
|
|
||||||
void (*_pfnGetSpawnParms) (edict_t*),
|
|
||||||
void (*_pfnSaveSpawnParms) (edict_t*),
|
|
||||||
float (*_pfnVecToYaw) (const float*),
|
|
||||||
void (*_pfnVecToAngles) (const float*, float*),
|
|
||||||
void (*_pfnMoveToOrigin) (edict_t*, const float*, float, int),
|
|
||||||
void (*_pfnChangeYaw) (edict_t*),
|
|
||||||
void (*_pfnChangePitch) (edict_t*),
|
|
||||||
edict_t* (*_pfnFindEntityByString) (edict_t*, const char*, const char*),
|
|
||||||
int (*_pfnGetEntityIllum) (edict_t*),
|
|
||||||
edict_t* (*_pfnFindEntityInSphere) (edict_t*, const float*, float),
|
|
||||||
edict_t* (*_pfnFindClientInPVS) (edict_t*),
|
|
||||||
edict_t* (*_pfnEntitiesInPVS) (edict_t*),
|
|
||||||
void (*_pfnMakeVectors) (const float*),
|
|
||||||
void (*_pfnAngleVectors) (const float*, float*, float*, float*),
|
|
||||||
edict_t* (*_pfnCreateEntity) (void),
|
|
||||||
void (*_pfnRemoveEntity) (edict_t*),
|
|
||||||
edict_t* (*_pfnCreateNamedEntity) (int),
|
|
||||||
void (*_pfnMakeStatic) (edict_t*),
|
|
||||||
int (*_pfnEntIsOnFloor) (edict_t*),
|
|
||||||
int (*_pfnDropToFloor) (edict_t*),
|
|
||||||
int (*_pfnWalkMove) (edict_t*, float, float, int),
|
|
||||||
void (*_pfnSetOrigin) (edict_t*, const float*),
|
|
||||||
void (*_pfnEmitSound) (edict_t*, int, const char*, float, float, int, int),
|
|
||||||
void (*_pfnEmitAmbientSound) (edict_t*, float*, const char*, float, float, int, int),
|
|
||||||
void (*_pfnTraceLine) (const float*, const float*, int, edict_t*, TraceResult*),
|
|
||||||
void (*_pfnTraceToss) (edict_t*, edict_t*, TraceResult*),
|
|
||||||
int (*_pfnTraceMonsterHull) (edict_t*, const float*, const float*, int, edict_t*, TraceResult*),
|
|
||||||
void (*_pfnTraceHull) (const float*, const float*, int, int, edict_t*, TraceResult*),
|
|
||||||
void (*_pfnTraceModel) (const float*, const float*, int, edict_t*, TraceResult*),
|
|
||||||
const char* (*_pfnTraceTexture) (edict_t*, const float*, const float*),
|
|
||||||
void (*_pfnTraceSphere) (const float*, const float*, int, float, edict_t*, TraceResult*),
|
|
||||||
void (*_pfnGetAimVector) (edict_t*, float, float*),
|
|
||||||
void (*_pfnServerCommand) (char*),
|
|
||||||
void (*_pfnServerExecute) (void),
|
|
||||||
void (*_pfnClientCommand) (edict_t*, char*, ...),
|
|
||||||
void (*_pfnParticleEffect) (const float*, const float*, float, float),
|
|
||||||
void (*_pfnLightStyle) (int, char*),
|
|
||||||
int (*_pfnDecalIndex) (const char*),
|
|
||||||
int (*_pfnPointContents) (const float*),
|
|
||||||
void (*_pfnMessageBegin) (int, int, const float*, edict_t*),
|
|
||||||
void (*_pfnMessageEnd) (void),
|
|
||||||
void (*_pfnWriteByte) (int),
|
|
||||||
void (*_pfnWriteChar) (int),
|
|
||||||
void (*_pfnWriteShort) (int),
|
|
||||||
void (*_pfnWriteLong) (int),
|
|
||||||
void (*_pfnWriteAngle) (float),
|
|
||||||
void (*_pfnWriteCoord) (float),
|
|
||||||
void (*_pfnWriteString) (const char*),
|
|
||||||
void (*_pfnWriteEntity) (int),
|
|
||||||
void (*_pfnCVarRegister) (cvar_t*),
|
|
||||||
float (*_pfnCVarGetFloat) (const char*),
|
|
||||||
const char* (*_pfnCVarGetString) (const char*),
|
|
||||||
void (*_pfnCVarSetFloat) (const char*, float),
|
|
||||||
void (*_pfnCVarSetString) (const char*, const char*),
|
|
||||||
void (*_pfnAlertMessage) (ALERT_TYPE, char*, ...),
|
|
||||||
void (*_pfnEngineFprintf) (void*, char*, ...),
|
|
||||||
void* (*_pfnPvAllocEntPrivateData) (edict_t*, int32),
|
|
||||||
void* (*_pfnPvEntPrivateData) (edict_t*),
|
|
||||||
void (*_pfnFreeEntPrivateData) (edict_t*),
|
|
||||||
const char* (*_pfnSzFromIndex) (int),
|
|
||||||
int (*_pfnAllocString) (const char*),
|
|
||||||
struct entvars_s*(*_pfnGetVarsOfEnt) (edict_t*),
|
|
||||||
edict_t* (*_pfnPEntityOfEntOffset) (int),
|
|
||||||
int (*_pfnEntOffsetOfPEntity) (const edict_t*),
|
|
||||||
int (*_pfnIndexOfEdict) (const edict_t*),
|
|
||||||
edict_t* (*_pfnPEntityOfEntIndex) (int),
|
|
||||||
edict_t* (*_pfnFindEntityByVars) (struct entvars_s*),
|
|
||||||
void* (*_pfnGetModelPtr) (edict_t*),
|
|
||||||
int (*_pfnRegUserMsg) (const char*, int),
|
|
||||||
void (*_pfnAnimationAutomove) (const edict_t*, float),
|
|
||||||
void (*_pfnGetBonePosition) (const edict_t*, int, float*, float* ),
|
|
||||||
uint32 (*_pfnFunctionFromName) (const char*),
|
|
||||||
const char* (*_pfnNameForFunction) (uint32),
|
|
||||||
void (*_pfnClientPrintf) (edict_t*, PRINT_TYPE, const char*),
|
|
||||||
void (*_pfnServerPrint) (const char*),
|
|
||||||
const char* (*_pfnCmd_Args) (void),
|
|
||||||
const char* (*_pfnCmd_Argv) (int argc),
|
|
||||||
int (*_pfnCmd_Argc) (void),
|
|
||||||
void (*_pfnGetAttachment) (const edict_t*, int, float*, float*),
|
|
||||||
void (*_pfnCRC32_Init) (CRC32_t*),
|
|
||||||
void (*_pfnCRC32_ProcessBuffer) (CRC32_t*, void*, int),
|
|
||||||
void (*_pfnCRC32_ProcessByte) (CRC32_t*, unsigned char),
|
|
||||||
CRC32_t (*_pfnCRC32_Final) (CRC32_t),
|
|
||||||
int32 (*_pfnRandomLong) (int32, int32),
|
|
||||||
float (*_pfnRandomFloat) (float, float),
|
|
||||||
void (*_pfnSetView) (const edict_t*, const edict_t*),
|
|
||||||
float (*_pfnTime) (void),
|
|
||||||
void (*_pfnCrosshairAngle) (const edict_t*, float, float),
|
|
||||||
byte* (*_pfnLoadFileForMe) (char*, int*),
|
|
||||||
void (*_pfnFreeFile) (void*),
|
|
||||||
void (*_pfnEndSection) (const char*),
|
|
||||||
int (*_pfnCompareFileTime) (char*, char*, int*),
|
|
||||||
void (*_pfnGetGameDir) (char*),
|
|
||||||
void (*_pfnCvar_RegisterVariable) (cvar_t*),
|
|
||||||
void (*_pfnFadeClientVolume) (const edict_t*, int, int, int, int),
|
|
||||||
void (*_pfnSetClientMaxspeed) (const edict_t*, float),
|
|
||||||
edict_t* (*_pfnCreateFakeClient) (const char*),
|
|
||||||
void (*_pfnRunPlayerMove) (edict_t*, const float*, float, float, float, unsigned short, byte, byte),
|
|
||||||
int (*_pfnNumberOfEntities) (void),
|
|
||||||
char* (*_pfnGetInfoKeyBuffer) (edict_t*),
|
|
||||||
char* (*_pfnInfoKeyValue) (char*, char*),
|
|
||||||
void (*_pfnSetKeyValue) (char*, char*, char*),
|
|
||||||
void (*_pfnSetClientKeyValue) (int, char*, char*, char*),
|
|
||||||
int (*_pfnIsMapValid) (char*),
|
|
||||||
void (*_pfnStaticDecal) (const float*, int, int, int),
|
|
||||||
int (*_pfnPrecacheGeneric) (char*),
|
|
||||||
int (*_pfnGetPlayerUserId) (edict_t*),
|
|
||||||
void (*_pfnBuildSoundMsg) (edict_t*, int, const char*, float, float, int, int, int, int, const float*, edict_t*),
|
|
||||||
int (*_pfnIsDedicatedServer) (void),
|
|
||||||
cvar_t* (*_pfnCVarGetPointer) (const char*),
|
|
||||||
unsigned int (*_pfnGetPlayerWONId) (edict_t*),
|
|
||||||
void (*_pfnInfo_RemoveKey) (char*, const char*),
|
|
||||||
const char* (*_pfnGetPhysicsKeyValue) (const edict_t*, const char*),
|
|
||||||
void (*_pfnSetPhysicsKeyValue) (const edict_t*, const char*, const char*),
|
|
||||||
const char* (*_pfnGetPhysicsInfoString) (const edict_t*),
|
|
||||||
unsigned short (*_pfnPrecacheEvent) (int, const char*),
|
|
||||||
void (*_pfnPlaybackEvent) (int, const edict_t*, unsigned short, float, float*, float*, float, float, int, int, int, int),
|
|
||||||
unsigned char* (*_pfnSetFatPVS) (float*),
|
|
||||||
unsigned char* (*_pfnSetFatPAS) (float*),
|
|
||||||
int (*_pfnCheckVisibility) (const edict_t*, unsigned char*),
|
|
||||||
void (*_pfnDeltaSetField) (struct delta_s*, const char*),
|
|
||||||
void (*_pfnDeltaUnsetField) (struct delta_s*, const char*),
|
|
||||||
void (*_pfnDeltaAddEncoder) (char*, void (*)(struct delta_s*, const unsigned char*, const unsigned char*)),
|
|
||||||
int (*_pfnGetCurrentPlayer) (void),
|
|
||||||
int (*_pfnCanSkipPlayer) (const edict_t*),
|
|
||||||
int (*_pfnDeltaFindField) (struct delta_s*, const char*),
|
|
||||||
void (*_pfnDeltaSetFieldByIndex) (struct delta_s*, int),
|
|
||||||
void (*_pfnDeltaUnsetFieldByIndex) (struct delta_s*, int),
|
|
||||||
void (*_pfnSetGroupMask) (int, int),
|
|
||||||
int (*_pfnCreateInstancedBaseline) (int, struct entity_state_s*),
|
|
||||||
void (*_pfnCvar_DirectSet) (struct cvar_s*, char*),
|
|
||||||
void (*_pfnForceUnmodified) (FORCE_TYPE, float*, float*, const char*),
|
|
||||||
void (*_pfnGetPlayerStats) (const edict_t*, int*, int*),
|
|
||||||
void (*_pfnAddServerCommand) (char*, void (*) (void)),
|
|
||||||
qboolean (*_pfnVoice_GetClientListening) (int, int),
|
|
||||||
qboolean (*_pfnVoice_SetClientListening) (int, int, qboolean),
|
|
||||||
const char* (*_pfnGetPlayerAuthId) (edict_t*),
|
|
||||||
sequenceEntry_s* (*_pfnSequenceGet) (const char*, const char*),
|
|
||||||
sentenceEntry_s* (*_pfnSequencePickSentence) (const char*, int, int*),
|
|
||||||
int (*_pfnGetFileSize) (char*),
|
|
||||||
unsigned int (*_pfnGetApproxWavePlayLen) (const char*),
|
|
||||||
int (*_pfnIsCareerMatch) (void),
|
|
||||||
int (*_pfnGetLocalizedStringLength) (const char*),
|
|
||||||
void (*_pfnRegisterTutorMessageShown) (int),
|
|
||||||
int (*_pfnGetTimesTutorMessageShown) (int),
|
|
||||||
void (*_pfnProcessTutorMessageDecayBuffer) (int*, int),
|
|
||||||
void (*_pfnConstructTutorMessageDecayBuffer)(int*, int),
|
|
||||||
void (*_pfnResetTutorMessageDecayData) (void),
|
|
||||||
void (*_pfnQueryClientCvarValue) (const edict_t*, const char*),
|
|
||||||
void (*_pfnQueryClientCvarValue2) (const edict_t*, const char*, int),
|
|
||||||
int (*_pfnEngCheckParm) (const char*, char**)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
pfnPrecacheModel = _pfnPrecacheModel;
|
|
||||||
pfnPrecacheSound = _pfnPrecacheSound;
|
|
||||||
pfnSetModel = _pfnSetModel;
|
|
||||||
pfnModelIndex = _pfnModelIndex;
|
|
||||||
pfnModelFrames = _pfnModelFrames;
|
|
||||||
pfnSetSize = _pfnSetSize;
|
|
||||||
pfnChangeLevel = _pfnChangeLevel;
|
|
||||||
pfnGetSpawnParms = _pfnGetSpawnParms;
|
|
||||||
pfnSaveSpawnParms = _pfnSaveSpawnParms;
|
|
||||||
pfnVecToYaw = _pfnVecToYaw;
|
|
||||||
pfnVecToAngles = _pfnVecToAngles;
|
|
||||||
pfnMoveToOrigin = _pfnMoveToOrigin;
|
|
||||||
pfnChangeYaw = _pfnChangeYaw;
|
|
||||||
pfnChangePitch = _pfnChangePitch;
|
|
||||||
pfnFindEntityByString = _pfnFindEntityByString;
|
|
||||||
pfnGetEntityIllum = _pfnGetEntityIllum;
|
|
||||||
pfnFindEntityInSphere = _pfnFindEntityInSphere;
|
|
||||||
pfnFindClientInPVS = _pfnFindClientInPVS;
|
|
||||||
pfnEntitiesInPVS = _pfnEntitiesInPVS;
|
|
||||||
pfnMakeVectors = _pfnMakeVectors;
|
|
||||||
pfnAngleVectors = _pfnAngleVectors;
|
|
||||||
pfnCreateEntity = _pfnCreateEntity;
|
|
||||||
pfnRemoveEntity = _pfnRemoveEntity;
|
|
||||||
pfnCreateNamedEntity = _pfnCreateNamedEntity;
|
|
||||||
pfnMakeStatic = _pfnMakeStatic;
|
|
||||||
pfnEntIsOnFloor = _pfnEntIsOnFloor;
|
|
||||||
pfnDropToFloor = _pfnDropToFloor;
|
|
||||||
pfnWalkMove = _pfnWalkMove;
|
|
||||||
pfnSetOrigin = _pfnSetOrigin;
|
|
||||||
pfnEmitSound = _pfnEmitSound;
|
|
||||||
pfnEmitAmbientSound = _pfnEmitAmbientSound;
|
|
||||||
pfnTraceLine = _pfnTraceLine;
|
|
||||||
pfnTraceToss = _pfnTraceToss;
|
|
||||||
pfnTraceMonsterHull = _pfnTraceMonsterHull;
|
|
||||||
pfnTraceHull = _pfnTraceHull;
|
|
||||||
pfnTraceModel = _pfnTraceModel;
|
|
||||||
pfnTraceTexture = _pfnTraceTexture;
|
|
||||||
pfnTraceSphere = _pfnTraceSphere;
|
|
||||||
pfnGetAimVector = _pfnGetAimVector;
|
|
||||||
pfnServerCommand = _pfnServerCommand;
|
|
||||||
pfnServerExecute = _pfnServerExecute;
|
|
||||||
pfnClientCommand = _pfnClientCommand;
|
|
||||||
pfnParticleEffect = _pfnParticleEffect;
|
|
||||||
pfnLightStyle = _pfnLightStyle;
|
|
||||||
pfnDecalIndex = _pfnDecalIndex;
|
|
||||||
pfnPointContents = _pfnPointContents;
|
|
||||||
pfnMessageBegin = _pfnMessageBegin;
|
|
||||||
pfnMessageEnd = _pfnMessageEnd;
|
|
||||||
pfnWriteByte = _pfnWriteByte;
|
|
||||||
pfnWriteChar = _pfnWriteChar;
|
|
||||||
pfnWriteShort = _pfnWriteShort;
|
|
||||||
pfnWriteLong = _pfnWriteLong;
|
|
||||||
pfnWriteAngle = _pfnWriteAngle;
|
|
||||||
pfnWriteCoord = _pfnWriteCoord;
|
|
||||||
pfnWriteString = _pfnWriteString;
|
|
||||||
pfnWriteEntity = _pfnWriteEntity;
|
|
||||||
pfnCVarRegister = _pfnCVarRegister;
|
|
||||||
pfnCVarGetFloat = _pfnCVarGetFloat;
|
|
||||||
pfnCVarGetString = _pfnCVarGetString;
|
|
||||||
pfnCVarSetFloat = _pfnCVarSetFloat;
|
|
||||||
pfnCVarSetString = _pfnCVarSetString;
|
|
||||||
pfnAlertMessage = _pfnAlertMessage;
|
|
||||||
pfnEngineFprintf = _pfnEngineFprintf;
|
|
||||||
pfnPvAllocEntPrivateData = _pfnPvAllocEntPrivateData;
|
|
||||||
pfnPvEntPrivateData = _pfnPvEntPrivateData;
|
|
||||||
pfnFreeEntPrivateData = _pfnFreeEntPrivateData;
|
|
||||||
pfnSzFromIndex = _pfnSzFromIndex;
|
|
||||||
pfnAllocString = _pfnAllocString;
|
|
||||||
pfnGetVarsOfEnt = _pfnGetVarsOfEnt;
|
|
||||||
pfnPEntityOfEntOffset = _pfnPEntityOfEntOffset;
|
|
||||||
pfnEntOffsetOfPEntity = _pfnEntOffsetOfPEntity;
|
|
||||||
pfnIndexOfEdict = _pfnIndexOfEdict;
|
|
||||||
pfnPEntityOfEntIndex = _pfnPEntityOfEntIndex;
|
|
||||||
pfnFindEntityByVars = _pfnFindEntityByVars;
|
|
||||||
pfnGetModelPtr = _pfnGetModelPtr;
|
|
||||||
pfnRegUserMsg = _pfnRegUserMsg;
|
|
||||||
pfnAnimationAutomove = _pfnAnimationAutomove;
|
|
||||||
pfnGetBonePosition = _pfnGetBonePosition;
|
|
||||||
pfnFunctionFromName = _pfnFunctionFromName;
|
|
||||||
pfnNameForFunction = _pfnNameForFunction;
|
|
||||||
pfnClientPrintf = _pfnClientPrintf;
|
|
||||||
pfnServerPrint = _pfnServerPrint;
|
|
||||||
pfnCmd_Args = _pfnCmd_Args;
|
|
||||||
pfnCmd_Argv = _pfnCmd_Argv;
|
|
||||||
pfnCmd_Argc = _pfnCmd_Argc;
|
|
||||||
pfnGetAttachment = _pfnGetAttachment;
|
|
||||||
pfnCRC32_Init = _pfnCRC32_Init;
|
|
||||||
pfnCRC32_ProcessBuffer = _pfnCRC32_ProcessBuffer;
|
|
||||||
pfnCRC32_ProcessByte = _pfnCRC32_ProcessByte;
|
|
||||||
pfnCRC32_Final = _pfnCRC32_Final;
|
|
||||||
pfnRandomLong = _pfnRandomLong;
|
|
||||||
pfnRandomFloat = _pfnRandomFloat;
|
|
||||||
pfnSetView = _pfnSetView;
|
|
||||||
pfnTime = _pfnTime;
|
|
||||||
pfnCrosshairAngle = _pfnCrosshairAngle;
|
|
||||||
pfnLoadFileForMe = _pfnLoadFileForMe;
|
|
||||||
pfnFreeFile = _pfnFreeFile;
|
|
||||||
pfnEndSection = _pfnEndSection;
|
|
||||||
pfnCompareFileTime = _pfnCompareFileTime;
|
|
||||||
pfnGetGameDir = _pfnGetGameDir;
|
|
||||||
pfnCvar_RegisterVariable = _pfnCvar_RegisterVariable;
|
|
||||||
pfnFadeClientVolume = _pfnFadeClientVolume;
|
|
||||||
pfnSetClientMaxspeed = _pfnSetClientMaxspeed;
|
|
||||||
pfnCreateFakeClient = _pfnCreateFakeClient;
|
|
||||||
pfnRunPlayerMove = _pfnRunPlayerMove;
|
|
||||||
pfnNumberOfEntities = _pfnNumberOfEntities;
|
|
||||||
pfnGetInfoKeyBuffer = _pfnGetInfoKeyBuffer;
|
|
||||||
pfnInfoKeyValue = _pfnInfoKeyValue;
|
|
||||||
pfnSetKeyValue = _pfnSetKeyValue;
|
|
||||||
pfnSetClientKeyValue = _pfnSetClientKeyValue;
|
|
||||||
pfnIsMapValid = _pfnIsMapValid;
|
|
||||||
pfnStaticDecal = _pfnStaticDecal;
|
|
||||||
pfnPrecacheGeneric = _pfnPrecacheGeneric;
|
|
||||||
pfnGetPlayerUserId = _pfnGetPlayerUserId;
|
|
||||||
pfnBuildSoundMsg = _pfnBuildSoundMsg;
|
|
||||||
pfnIsDedicatedServer = _pfnIsDedicatedServer;
|
|
||||||
pfnCVarGetPointer = _pfnCVarGetPointer;
|
|
||||||
pfnGetPlayerWONId = _pfnGetPlayerWONId;
|
|
||||||
pfnInfo_RemoveKey = _pfnInfo_RemoveKey;
|
|
||||||
pfnGetPhysicsKeyValue = _pfnGetPhysicsKeyValue;
|
|
||||||
pfnSetPhysicsKeyValue = _pfnSetPhysicsKeyValue;
|
|
||||||
pfnGetPhysicsInfoString = _pfnGetPhysicsInfoString;
|
|
||||||
pfnPrecacheEvent = _pfnPrecacheEvent;
|
|
||||||
pfnPlaybackEvent = _pfnPlaybackEvent;
|
|
||||||
pfnSetFatPVS = _pfnSetFatPVS;
|
|
||||||
pfnSetFatPAS = _pfnSetFatPAS;
|
|
||||||
pfnCheckVisibility = _pfnCheckVisibility;
|
|
||||||
pfnDeltaSetField = _pfnDeltaSetField;
|
|
||||||
pfnDeltaUnsetField = _pfnDeltaUnsetField;
|
|
||||||
pfnDeltaAddEncoder = _pfnDeltaAddEncoder;
|
|
||||||
pfnGetCurrentPlayer = _pfnGetCurrentPlayer;
|
|
||||||
pfnCanSkipPlayer = _pfnCanSkipPlayer;
|
|
||||||
pfnDeltaFindField = _pfnDeltaFindField;
|
|
||||||
pfnDeltaSetFieldByIndex = _pfnDeltaSetFieldByIndex;
|
|
||||||
pfnDeltaUnsetFieldByIndex = _pfnDeltaUnsetFieldByIndex;
|
|
||||||
pfnSetGroupMask = _pfnSetGroupMask;
|
|
||||||
pfnCreateInstancedBaseline = _pfnCreateInstancedBaseline;
|
|
||||||
pfnCvar_DirectSet = _pfnCvar_DirectSet;
|
|
||||||
pfnForceUnmodified = _pfnForceUnmodified;
|
|
||||||
pfnGetPlayerStats = _pfnGetPlayerStats;
|
|
||||||
pfnAddServerCommand = _pfnAddServerCommand;
|
|
||||||
pfnVoice_GetClientListening = _pfnVoice_GetClientListening;
|
|
||||||
pfnVoice_SetClientListening = _pfnVoice_SetClientListening;
|
|
||||||
pfnGetPlayerAuthId = _pfnGetPlayerAuthId;
|
|
||||||
pfnSequenceGet = _pfnSequenceGet;
|
|
||||||
pfnSequencePickSentence = _pfnSequencePickSentence;
|
|
||||||
pfnGetFileSize = _pfnGetFileSize;
|
|
||||||
pfnGetApproxWavePlayLen = _pfnGetApproxWavePlayLen;
|
|
||||||
pfnIsCareerMatch = _pfnIsCareerMatch;
|
|
||||||
pfnGetLocalizedStringLength = _pfnGetLocalizedStringLength;
|
|
||||||
pfnRegisterTutorMessageShown = _pfnRegisterTutorMessageShown;
|
|
||||||
pfnGetTimesTutorMessageShown = _pfnGetTimesTutorMessageShown;
|
|
||||||
pfnProcessTutorMessageDecayBuffer = _pfnProcessTutorMessageDecayBuffer;
|
|
||||||
pfnConstructTutorMessageDecayBuffer = _pfnConstructTutorMessageDecayBuffer;
|
|
||||||
pfnResetTutorMessageDecayData = _pfnResetTutorMessageDecayData;
|
|
||||||
pfnQueryClientCvarValue = _pfnQueryClientCvarValue;
|
|
||||||
pfnQueryClientCvarValue2 = _pfnQueryClientCvarValue2;
|
|
||||||
pfnEngCheckParm = _pfnEngCheckParm;
|
|
||||||
|
|
||||||
memset( extra_functions, 0, sizeof(extra_functions));
|
|
||||||
|
|
||||||
memset( dummies, 0, sizeof(pdummyfunc) * c_NumDummies );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
|
||||||
// HL_enginefuncs
|
|
||||||
// -----------------------------------------------------------------
|
|
||||||
|
|
||||||
void HL_enginefuncs_t::initialise_interface( enginefuncs_t *_pFuncs )
|
|
||||||
{
|
|
||||||
set_from( _pFuncs );
|
|
||||||
|
|
||||||
// Now the pfnAlertMessage is available and we trust it to be a valid
|
|
||||||
// pointer, so flush the message buffer.
|
|
||||||
flush_ALERT_buffer();
|
|
||||||
|
|
||||||
determine_engine_interface_version();
|
|
||||||
fixup_engine_interface();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// The following part (i.e. the end) of the enginefuncs_t struct is
|
|
||||||
// used to determine the engine interface version since it is the one
|
|
||||||
// that changed since SDK 212 engines. We call this the "signature" of
|
|
||||||
// the enginefuncs interface.
|
|
||||||
//
|
|
||||||
// Default version is 138. That's what the SDK says.
|
|
||||||
//
|
|
||||||
// 144: const char *(*pfnGetPlayerAuthId) ( edict_t *e );
|
|
||||||
//
|
|
||||||
// // PSV: Added for CZ training map
|
|
||||||
// // const char *(*pfnKeyNameForBinding) ( const char* pBinding );
|
|
||||||
//
|
|
||||||
// sequenceEntry_s* (*pfnSequenceGet) ( const char* fileName, const char* entryName );
|
|
||||||
// sentenceEntry_s* (*pfnSequencePickSentence) ( const char* groupName, int pickMethod, int *picked );
|
|
||||||
//
|
|
||||||
// // LH: Give access to filesize via filesystem
|
|
||||||
// 147: int (*pfnGetFileSize) ( char *filename );
|
|
||||||
//
|
|
||||||
// unsigned int (*pfnGetApproxWavePlayLen) (const char *filepath);
|
|
||||||
// // MDC: Added for CZ career-mode
|
|
||||||
// int (*pfnIsCareerMatch) ( void );
|
|
||||||
//
|
|
||||||
// // BGC: return the number of characters of the localized string referenced by using "label"
|
|
||||||
// int (*pfnGetLocalizedStringLength) (const char *label);
|
|
||||||
//
|
|
||||||
// // BGC: added to facilitate persistent storage of tutor message decay values for
|
|
||||||
// // different career game profiles. Also needs to persist regardless of mp.dll being
|
|
||||||
// // destroyed and recreated.
|
|
||||||
// void (*pfnRegisterTutorMessageShown) (int mid);
|
|
||||||
// int (*pfnGetTimesTutorMessageShown) (int mid);
|
|
||||||
// void (*pfnProcessTutorMessageDecayBuffer) (int *buffer, int bufferLength);
|
|
||||||
// void (*pfnConstructTutorMessageDecayBuffer) (int *buffer, int bufferLength);
|
|
||||||
// 155: void (*pfnResetTutorMessageDecayData) ( void );
|
|
||||||
|
|
||||||
// 156: void (*pfnQueryClientCvarValue) ( const edict_t *player, const char *cvarName );
|
|
||||||
// 157: void (*pfnQueryClientCvarValue2) ( const edict_t *player, const char *cvarName, int requestID );
|
|
||||||
// 158: int (*pfnEngCheckParm) ( const char *pchCmdLineToke, char **pchNextValue );
|
|
||||||
|
|
||||||
void HL_enginefuncs_t::determine_engine_interface_version( void )
|
|
||||||
{
|
|
||||||
// We only need to do this once.
|
|
||||||
if (0 != sm_version) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test every pointer that is part of the signature if it is a valid
|
|
||||||
// pointer. If it is not, we set it explicitly to NULL.
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnGetPlayerAuthId) ) {
|
|
||||||
pfnGetPlayerAuthId = NULL;
|
|
||||||
}
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnSequenceGet) ) {
|
|
||||||
pfnSequenceGet = NULL;
|
|
||||||
}
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnSequencePickSentence) ) {
|
|
||||||
pfnSequencePickSentence = NULL;
|
|
||||||
}
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnGetFileSize) ) {
|
|
||||||
pfnGetFileSize = NULL;
|
|
||||||
}
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnGetApproxWavePlayLen) ) {
|
|
||||||
pfnGetApproxWavePlayLen = NULL;
|
|
||||||
}
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnIsCareerMatch) ) {
|
|
||||||
pfnIsCareerMatch = NULL;
|
|
||||||
}
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnGetLocalizedStringLength) ) {
|
|
||||||
pfnGetLocalizedStringLength = NULL;
|
|
||||||
}
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnRegisterTutorMessageShown) ) {
|
|
||||||
pfnRegisterTutorMessageShown = NULL;
|
|
||||||
}
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnGetTimesTutorMessageShown) ) {
|
|
||||||
pfnGetTimesTutorMessageShown = NULL;
|
|
||||||
}
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnProcessTutorMessageDecayBuffer) ) {
|
|
||||||
pfnProcessTutorMessageDecayBuffer = NULL;
|
|
||||||
}
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnConstructTutorMessageDecayBuffer) ) {
|
|
||||||
pfnConstructTutorMessageDecayBuffer = NULL;
|
|
||||||
}
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnResetTutorMessageDecayData) ) {
|
|
||||||
pfnResetTutorMessageDecayData = NULL;
|
|
||||||
}
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnQueryClientCvarValue) ) {
|
|
||||||
pfnQueryClientCvarValue = NULL;
|
|
||||||
}
|
|
||||||
if ( ! Engine.info.is_valid_code_pointer(pfnQueryClientCvarValue2) ) {
|
|
||||||
pfnQueryClientCvarValue2 = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now begins our heuristic, where we try to determine the engine
|
|
||||||
// interface version.
|
|
||||||
// As alluded to above we are currently only interested, and thus
|
|
||||||
// only detect, versions 144, 147, 156 or 157 (defined by us).
|
|
||||||
|
|
||||||
// The minimal default is 138.
|
|
||||||
sm_version = 138;
|
|
||||||
|
|
||||||
// If GetPlayerAuthId() is present, it is at least 144,
|
|
||||||
// otherwise leave it at the default 138.
|
|
||||||
// This may give incorrect results for *really* old engine versions,
|
|
||||||
// i.e. pre 1.1.0.8. We live with that risk. No one uses them anymore.
|
|
||||||
// Really.
|
|
||||||
if ( pfnGetPlayerAuthId == NULL ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sm_version = 144;
|
|
||||||
|
|
||||||
// The two function pointers for pfnSequenceGet() and
|
|
||||||
// pfnSequencePickSentence() are only valid in a few engine versions
|
|
||||||
// and are set to NULL in most other version, so they don't get
|
|
||||||
// checked.
|
|
||||||
|
|
||||||
// If pfnGetFileSize() is present, it is at least 147,
|
|
||||||
// otherwise leave it at the so far determined value.
|
|
||||||
if ( pfnGetFileSize == NULL ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sm_version = 147;
|
|
||||||
|
|
||||||
// Now it gets a bit fuzzy. If all of the functions following GetFileSize()
|
|
||||||
// but before QueryClientCvarValue() are valid, it is at least 155.
|
|
||||||
// If even one of them is NULL, then our version can't be higher than 147,
|
|
||||||
// so use 147. Actually, it could be that there exist engine
|
|
||||||
// versions where one of them is NULL but the interface is still at
|
|
||||||
// least 155. If such an engine is found in use, adaptions need to be
|
|
||||||
// made.
|
|
||||||
// (Yes, I know this could be done with a little hacky for() loop. We
|
|
||||||
// don't need to do hacky here.)
|
|
||||||
int cntInvals = 0;
|
|
||||||
if ( pfnGetApproxWavePlayLen == NULL ) cntInvals++;
|
|
||||||
if ( pfnIsCareerMatch == NULL ) cntInvals++;
|
|
||||||
if ( pfnGetLocalizedStringLength == NULL ) cntInvals++;
|
|
||||||
if ( pfnRegisterTutorMessageShown == NULL ) cntInvals++;
|
|
||||||
if ( pfnGetTimesTutorMessageShown == NULL ) cntInvals++;
|
|
||||||
if ( pfnProcessTutorMessageDecayBuffer == NULL ) cntInvals++;
|
|
||||||
if ( pfnConstructTutorMessageDecayBuffer == NULL ) cntInvals++;
|
|
||||||
if ( pfnResetTutorMessageDecayData == NULL ) cntInvals++;
|
|
||||||
|
|
||||||
if ( cntInvals > 0 ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sm_version = 155;
|
|
||||||
|
|
||||||
// All functions up to QueryClientCvarValue() are valid.
|
|
||||||
// If QueryClientCvarValue() is not valid, leave it at the so far
|
|
||||||
// determined version. Otherwise the version is at least 156.
|
|
||||||
if ( pfnQueryClientCvarValue == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sm_version = 156;
|
|
||||||
|
|
||||||
// All functions up to QueryClientCvarValue2() are valid.
|
|
||||||
// If QueryClientCvarValue2() is not valid, leave it at the so far
|
|
||||||
// determined version. Otherwise the version is at least 157.
|
|
||||||
if ( pfnQueryClientCvarValue2 == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sm_version = 157;
|
|
||||||
|
|
||||||
// All functions up to EngCheckParm() are valid.
|
|
||||||
// If EngCheckParm() is not valid, leave it at the so far determined
|
|
||||||
// version. Otherwise the version is at least 158.
|
|
||||||
if ( pfnEngCheckParm == NULL) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sm_version = 158;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void HL_enginefuncs_t::fixup_engine_interface( void )
|
|
||||||
{
|
|
||||||
// This function will make sure that all function pointers that aren't
|
|
||||||
// valid are set to NULL, depending on the engine interface version.
|
|
||||||
// Sometimes a pointer has a valid value although the function doesn't
|
|
||||||
// exist in the interface version.
|
|
||||||
|
|
||||||
switch ( version() ) {
|
|
||||||
case 138:
|
|
||||||
pfnGetPlayerAuthId = NULL;
|
|
||||||
case 144:
|
|
||||||
pfnSequenceGet = NULL;
|
|
||||||
pfnSequencePickSentence = NULL;
|
|
||||||
pfnGetFileSize = NULL;
|
|
||||||
case 147:
|
|
||||||
pfnGetApproxWavePlayLen = NULL;
|
|
||||||
pfnIsCareerMatch = NULL;
|
|
||||||
pfnGetLocalizedStringLength = NULL;
|
|
||||||
pfnRegisterTutorMessageShown = NULL;
|
|
||||||
pfnGetTimesTutorMessageShown = NULL;
|
|
||||||
pfnProcessTutorMessageDecayBuffer = NULL;
|
|
||||||
pfnConstructTutorMessageDecayBuffer = NULL;
|
|
||||||
pfnResetTutorMessageDecayData = NULL;
|
|
||||||
case 155:
|
|
||||||
pfnQueryClientCvarValue = NULL;
|
|
||||||
case 156:
|
|
||||||
pfnQueryClientCvarValue2 = NULL;
|
|
||||||
case 157:
|
|
||||||
pfnEngCheckParm = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,459 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// metamod.cpp - (main) implementation of metamod operations
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <malloc.h> // malloc, etc
|
|
||||||
#include <errno.h> // errno, etc
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
#include "enginecallbacks.h" // GET_GAME_DIR, etc
|
|
||||||
|
|
||||||
#include "metamod.h" // me
|
|
||||||
#include "h_export.h" // GIVE_ENGINE_FUNCTIONS_FN, etc
|
|
||||||
#include "mreg.h" // class mCmdList, etc
|
|
||||||
#include "meta_api.h" // meta_globals_t, etc
|
|
||||||
#include "mutil.h" // mutil_funcs_t, etc
|
|
||||||
#include "osdep.h" // DLOPEN, getcwd, is_absolute_path,
|
|
||||||
#include "reg_support.h" // meta_AddServerCommand, etc
|
|
||||||
#include "game_support.h" // lookup_game, etc
|
|
||||||
#include "commands_meta.h" // meta_register_cmdcvar, etc
|
|
||||||
#include "thread_logparse.h" // logparse_handle, etc
|
|
||||||
#include "support_meta.h" // valid_gamedir_file, etc
|
|
||||||
#include "log_meta.h" // META_LOG, etc
|
|
||||||
#include "types_meta.h" // mBOOL
|
|
||||||
#include "info_name.h" // VNAME, etc
|
|
||||||
#include "vdate.h" // COMPILE_TIME, etc
|
|
||||||
#include "linkent.h"
|
|
||||||
|
|
||||||
cvar_t meta_version = {"metamod_version", VVERSION, FCVAR_SERVER, 0, NULL};
|
|
||||||
|
|
||||||
MConfig static_config;
|
|
||||||
MConfig *Config=&static_config;
|
|
||||||
option_t global_options[] = {
|
|
||||||
{ "debuglevel", CF_INT, &Config->debuglevel, "0" },
|
|
||||||
{ "gamedll", CF_PATH, &Config->gamedll, NULL },
|
|
||||||
{ "plugins_file", CF_PATH, &Config->plugins_file, PLUGINS_INI },
|
|
||||||
{ "exec_cfg", CF_STR, &Config->exec_cfg, EXEC_CFG },
|
|
||||||
{ "autodetect", CF_BOOL, &Config->autodetect, "yes" },
|
|
||||||
{ "clientmeta", CF_BOOL, &Config->clientmeta, "yes" },
|
|
||||||
// list terminator
|
|
||||||
{ NULL, CF_NONE, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
gamedll_t GameDLL;
|
|
||||||
|
|
||||||
meta_globals_t PublicMetaGlobals;
|
|
||||||
meta_globals_t PrivateMetaGlobals;
|
|
||||||
|
|
||||||
meta_enginefuncs_t g_plugin_engfuncs;
|
|
||||||
|
|
||||||
MPluginList *Plugins;
|
|
||||||
MRegCmdList *RegCmds;
|
|
||||||
MRegCvarList *RegCvars;
|
|
||||||
MRegMsgList *RegMsgs;
|
|
||||||
|
|
||||||
MPlayerList g_Players;
|
|
||||||
int requestid_counter = 0;
|
|
||||||
|
|
||||||
DLHANDLE metamod_handle;
|
|
||||||
int metamod_not_loaded = 0;
|
|
||||||
|
|
||||||
|
|
||||||
// Very first metamod function that's run.
|
|
||||||
// Do startup operations...
|
|
||||||
int DLLINTERNAL metamod_startup(void) {
|
|
||||||
char *cp, *mmfile=NULL, *cfile=NULL;
|
|
||||||
|
|
||||||
META_CONS(" ");
|
|
||||||
META_CONS(" %s version %s Copyright (c) 2001-%s %s", VNAME, VVERSION, COPYRIGHT_YEAR, VAUTHOR);
|
|
||||||
META_CONS(" Patch: %s v%d Copyright (c) 2004-%s %s", VPATCH_NAME, VPATCH_IVERSION, VPATCH_COPYRIGHT_YEAR, VPATCH_AUTHOR);
|
|
||||||
META_CONS(" %s comes with ABSOLUTELY NO WARRANTY; for details type `meta gpl'.", VNAME);
|
|
||||||
META_CONS(" This is free software, and you are welcome to redistribute it");
|
|
||||||
META_CONS(" under certain conditions; type `meta gpl' for details.");
|
|
||||||
META_CONS(" ");
|
|
||||||
|
|
||||||
META_LOG("%s v%s %s", VNAME, VVERSION, VDATE);
|
|
||||||
META_LOG("by %s", VAUTHOR);
|
|
||||||
META_LOG(" %s", VURL);
|
|
||||||
META_LOG(" Patch: %s v%d", VPATCH_NAME, VPATCH_IVERSION);
|
|
||||||
META_LOG(" by %s", VPATCH_AUTHOR);
|
|
||||||
META_LOG(" %s", VPATCH_WEBSITE);
|
|
||||||
META_LOG("compiled: %s %s (%s)", COMPILE_TIME, COMPILE_TZONE, OPT_TYPE);
|
|
||||||
|
|
||||||
// If running with "+developer", allow an opportunity to break in with
|
|
||||||
// a debugger.
|
|
||||||
if((int)CVAR_GET_FLOAT("developer") != 0)
|
|
||||||
sleep(1);
|
|
||||||
|
|
||||||
// Get gamedir, very early on, because it seems we need it all over the
|
|
||||||
// place here at the start.
|
|
||||||
if(!meta_init_gamedll()) {
|
|
||||||
META_ERROR("Failure to init game DLL; exiting...");
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register various console commands and cvars.
|
|
||||||
// Can I do these here, rather than waiting for GameDLLInit() ?
|
|
||||||
// Looks like it works okay..
|
|
||||||
meta_register_cmdcvar();
|
|
||||||
{
|
|
||||||
//dirty hacks
|
|
||||||
int vers[4] = {RC_VERS_DWORD};
|
|
||||||
char mvers[32];
|
|
||||||
|
|
||||||
if(vers[2]==0)
|
|
||||||
safevoid_snprintf(mvers, sizeof(mvers), "%d.%dp%d", vers[0], vers[1], vers[3]);
|
|
||||||
else
|
|
||||||
safevoid_snprintf(mvers, sizeof(mvers), "%d.%d.%dp%d", vers[0], vers[1], vers[2], vers[3]);
|
|
||||||
|
|
||||||
CVAR_SET_STRING(meta_version.name, mvers);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set a slight debug level for developer mode, if debug level not
|
|
||||||
// already set.
|
|
||||||
if((int)CVAR_GET_FLOAT("developer") != 0 && (int)meta_debug.value == 0) {
|
|
||||||
CVAR_SET_FLOAT("meta_debug", (float)(meta_debug_value = 3));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init default values
|
|
||||||
Config->init(global_options);
|
|
||||||
// Find config file
|
|
||||||
cfile=CONFIG_INI;
|
|
||||||
if((cp=LOCALINFO("mm_configfile")) && *cp != '\0') {
|
|
||||||
META_LOG("Configfile specified via localinfo: %s", cp);
|
|
||||||
if(valid_gamedir_file(cp))
|
|
||||||
cfile=cp;
|
|
||||||
else
|
|
||||||
META_WARNING("Empty/missing config.ini file: %s; falling back to %s",
|
|
||||||
cp, cfile);
|
|
||||||
}
|
|
||||||
// Load config file
|
|
||||||
if(valid_gamedir_file(cfile))
|
|
||||||
Config->load(cfile);
|
|
||||||
else
|
|
||||||
META_DEBUG(2, ("No config.ini file found: %s", CONFIG_INI));
|
|
||||||
|
|
||||||
// Now, override config options with localinfo commandline options.
|
|
||||||
if((cp=LOCALINFO("mm_debug")) && *cp != '\0') {
|
|
||||||
META_LOG("Debuglevel specified via localinfo: %s", cp);
|
|
||||||
Config->set("debuglevel", cp);
|
|
||||||
}
|
|
||||||
if((cp=LOCALINFO("mm_gamedll")) && *cp != '\0') {
|
|
||||||
META_LOG("Gamedll specified via localinfo: %s", cp);
|
|
||||||
Config->set("gamedll", cp);
|
|
||||||
}
|
|
||||||
if((cp=LOCALINFO("mm_pluginsfile")) && *cp != '\0') {
|
|
||||||
META_LOG("Pluginsfile specified via localinfo: %s", cp);
|
|
||||||
Config->set("plugins_file", cp);
|
|
||||||
}
|
|
||||||
if((cp=LOCALINFO("mm_execcfg")) && *cp != '\0') {
|
|
||||||
META_LOG("Execcfg specified via localinfo: %s", cp);
|
|
||||||
Config->set("exec_cfg", cp);
|
|
||||||
}
|
|
||||||
if((cp=LOCALINFO("mm_autodetect")) && *cp != '\0') {
|
|
||||||
META_LOG("Autodetect specified via localinfo: %s", cp);
|
|
||||||
Config->set("autodetect", cp);
|
|
||||||
}
|
|
||||||
if((cp=LOCALINFO("mm_clientmeta")) && *cp != '\0') {
|
|
||||||
META_LOG("Clientmeta specified via localinfo: %s", cp);
|
|
||||||
Config->set("clientmeta", cp);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Check for an initial debug level, since cfg files don't get exec'd
|
|
||||||
// until later.
|
|
||||||
if(Config->debuglevel != 0) {
|
|
||||||
CVAR_SET_FLOAT("meta_debug", (float)(meta_debug_value = Config->debuglevel));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare for registered commands from plugins.
|
|
||||||
RegCmds = new MRegCmdList();
|
|
||||||
RegCvars = new MRegCvarList();
|
|
||||||
|
|
||||||
// Prepare for registered user messages from gamedll.
|
|
||||||
RegMsgs = new MRegMsgList();
|
|
||||||
|
|
||||||
// Copy, and store pointer in Engine struct. Yes, we could just store
|
|
||||||
// the actual engine_t struct in Engine, but then it wouldn't be a
|
|
||||||
// pointer to match the other g_engfuncs.
|
|
||||||
g_plugin_engfuncs.set_from(Engine.funcs);
|
|
||||||
Engine.pl_funcs=&g_plugin_engfuncs;
|
|
||||||
// substitute our special versions of various commands
|
|
||||||
Engine.pl_funcs->pfnAddServerCommand = meta_AddServerCommand;
|
|
||||||
Engine.pl_funcs->pfnCVarRegister = meta_CVarRegister;
|
|
||||||
Engine.pl_funcs->pfnCvar_RegisterVariable = meta_CVarRegister;
|
|
||||||
Engine.pl_funcs->pfnRegUserMsg = meta_RegUserMsg;
|
|
||||||
if(IS_VALID_PTR((void*)Engine.pl_funcs->pfnQueryClientCvarValue))
|
|
||||||
Engine.pl_funcs->pfnQueryClientCvarValue = meta_QueryClientCvarValue;
|
|
||||||
else
|
|
||||||
Engine.pl_funcs->pfnQueryClientCvarValue = NULL;
|
|
||||||
if(!IS_VALID_PTR((void*)Engine.pl_funcs->pfnQueryClientCvarValue2))
|
|
||||||
Engine.pl_funcs->pfnQueryClientCvarValue2 = NULL;
|
|
||||||
|
|
||||||
// Before, we loaded plugins before loading the game DLL, so that if no
|
|
||||||
// plugins caught engine functions, we could pass engine funcs straight
|
|
||||||
// to game dll, rather than acting as intermediary. (Should perform
|
|
||||||
// better, right?)
|
|
||||||
//
|
|
||||||
// But since a plugin can be loaded at any time, we have to go ahead
|
|
||||||
// and catch the engine funcs regardless. Also, we want to give each
|
|
||||||
// plugin a copy of the gameDLL's api tables, in case they need to call
|
|
||||||
// API functions directly.
|
|
||||||
//
|
|
||||||
// Thus, load gameDLL first, then plugins.
|
|
||||||
//
|
|
||||||
// However, we have to init the Plugins object first, because if the
|
|
||||||
// gamedll calls engine functions during GiveFnptrsToDll (like hpb_bot
|
|
||||||
// does) then it needs to be non-null so META_ENGINE_HANDLE won't crash.
|
|
||||||
//
|
|
||||||
// However, having replaced valid_file with valid_gamedir_file, we need
|
|
||||||
// to at least initialize the gameDLL to include the gamedir, before
|
|
||||||
// looking for plugins.ini.
|
|
||||||
//
|
|
||||||
// In fact, we need gamedir even earlier, so moved up above.
|
|
||||||
|
|
||||||
// Fall back to old plugins filename, if configured one isn't found.
|
|
||||||
mmfile=PLUGINS_INI;
|
|
||||||
if(!valid_gamedir_file(PLUGINS_INI) && valid_gamedir_file(OLD_PLUGINS_INI))
|
|
||||||
mmfile=OLD_PLUGINS_INI;
|
|
||||||
if(valid_gamedir_file(Config->plugins_file))
|
|
||||||
mmfile=Config->plugins_file;
|
|
||||||
else
|
|
||||||
META_WARNING("Plugins file is empty/missing: %s; falling back to %s",
|
|
||||||
Config->plugins_file, mmfile);
|
|
||||||
|
|
||||||
Plugins = new MPluginList(mmfile);
|
|
||||||
|
|
||||||
if(!meta_load_gamedll()) {
|
|
||||||
META_ERROR("Failure to load game DLL; exiting...");
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
if(!Plugins->load()) {
|
|
||||||
META_WARNING("Failure to load plugins...");
|
|
||||||
// Exit on failure here? Dunno...
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow for commands to metamod plugins at startup. Autoexec.cfg is
|
|
||||||
// read too early, and server.cfg is read too late.
|
|
||||||
//
|
|
||||||
// Only attempt load if the file appears to exist and be non-empty, to
|
|
||||||
// avoid confusing users with "couldn't exec exec.cfg" console
|
|
||||||
// messages.
|
|
||||||
if(valid_gamedir_file(Config->exec_cfg))
|
|
||||||
mmfile=Config->exec_cfg;
|
|
||||||
else if(valid_gamedir_file(OLD_EXEC_CFG))
|
|
||||||
mmfile=OLD_EXEC_CFG;
|
|
||||||
else
|
|
||||||
mmfile=NULL;
|
|
||||||
|
|
||||||
if(mmfile) {
|
|
||||||
if(mmfile[0]=='/')
|
|
||||||
META_WARNING("Cannot exec absolute pathnames: %s", mmfile);
|
|
||||||
else {
|
|
||||||
char cmd[NAME_MAX];
|
|
||||||
META_LOG("Exec'ing metamod exec.cfg: %s...", mmfile);
|
|
||||||
safevoid_snprintf(cmd, sizeof(cmd), "exec %s\n", mmfile);
|
|
||||||
SERVER_COMMAND(cmd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set initial GameDLL fields (name, gamedir).
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_NULLRESULT getcwd failed
|
|
||||||
mBOOL DLLINTERNAL meta_init_gamedll(void) {
|
|
||||||
char gamedir[PATH_MAX];
|
|
||||||
char *cp;
|
|
||||||
|
|
||||||
memset(&GameDLL, 0, sizeof(GameDLL));
|
|
||||||
|
|
||||||
GET_GAME_DIR(gamedir);
|
|
||||||
normalize_pathname(gamedir);
|
|
||||||
//
|
|
||||||
// As of 1.1.1.1, the engine routine GET_GAME_DIR no longer returns a
|
|
||||||
// full-pathname, but rather just the path specified as the argument to
|
|
||||||
// "-game".
|
|
||||||
//
|
|
||||||
// However, since we have to work properly under both the new version
|
|
||||||
// as well as previous versions, we have to support both possibilities.
|
|
||||||
//
|
|
||||||
// Note: the code has always assumed the server op wouldn't do:
|
|
||||||
// hlds -game other/firearms
|
|
||||||
//
|
|
||||||
if(is_absolute_path(gamedir)) {
|
|
||||||
// Old style; GET_GAME_DIR returned full pathname. Copy this into
|
|
||||||
// our gamedir, and truncate to get the game name.
|
|
||||||
// (note check for both linux and win32 full pathname.)
|
|
||||||
STRNCPY(GameDLL.gamedir, gamedir, sizeof(GameDLL.gamedir));
|
|
||||||
cp=strrchr(gamedir, '/') + 1;
|
|
||||||
STRNCPY(GameDLL.name, cp, sizeof(GameDLL.name));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// New style; GET_GAME_DIR returned game name. Copy this into our
|
|
||||||
// game name, and prepend the current working directory.
|
|
||||||
char buf[PATH_MAX];
|
|
||||||
if(!getcwd(buf, sizeof(buf))) {
|
|
||||||
META_WARNING("dll: Couldn't get cwd; %s", strerror(errno));
|
|
||||||
RETURN_ERRNO(mFALSE, ME_NULLRESULT);
|
|
||||||
}
|
|
||||||
safevoid_snprintf(GameDLL.gamedir, sizeof(GameDLL.gamedir),
|
|
||||||
"%s/%s", buf, gamedir);
|
|
||||||
STRNCPY(GameDLL.name, gamedir, sizeof(GameDLL.name));
|
|
||||||
}
|
|
||||||
|
|
||||||
META_DEBUG(3, ("Game: %s", GameDLL.name));
|
|
||||||
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load game DLL.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_DLOPEN couldn't dlopen game dll file
|
|
||||||
// - ME_DLMISSING couldn't find required routine in game dll
|
|
||||||
// (GiveFnptrsToDll, GetEntityAPI, GetEntityAPI2)
|
|
||||||
mBOOL DLLINTERNAL meta_load_gamedll(void) {
|
|
||||||
int iface_vers;
|
|
||||||
int found=0;
|
|
||||||
|
|
||||||
GIVE_ENGINE_FUNCTIONS_FN pfn_give_engfuncs;
|
|
||||||
GETNEWDLLFUNCTIONS_FN pfn_getapinew;
|
|
||||||
GETENTITYAPI2_FN pfn_getapi2;
|
|
||||||
GETENTITYAPI_FN pfn_getapi;
|
|
||||||
|
|
||||||
if(!setup_gamedll(&GameDLL)) {
|
|
||||||
META_WARNING("dll: Unrecognized game: %s", GameDLL.name);
|
|
||||||
// meta_errno should be already set in lookup_game()
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// open the game DLL
|
|
||||||
if(!(GameDLL.handle=DLOPEN(GameDLL.pathname))) {
|
|
||||||
META_WARNING("dll: Couldn't load game DLL %s: %s", GameDLL.pathname,
|
|
||||||
DLERROR());
|
|
||||||
RETURN_ERRNO(mFALSE, ME_DLOPEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used to only pass our table of engine funcs if a loaded plugin
|
|
||||||
// wanted to catch one of the functions, but now that plugins are
|
|
||||||
// dynamically loadable at any time, we have to always pass our table,
|
|
||||||
// so that any plugin loaded later can catch what they need to.
|
|
||||||
if((pfn_give_engfuncs = (GIVE_ENGINE_FUNCTIONS_FN) DLSYM(GameDLL.handle, "GiveFnptrsToDll")))
|
|
||||||
{
|
|
||||||
pfn_give_engfuncs(&meta_engfuncs, gpGlobals);
|
|
||||||
META_DEBUG(3, ("dll: Game '%s': Called GiveFnptrsToDll",
|
|
||||||
GameDLL.name));
|
|
||||||
|
|
||||||
//activate linkent-replacement after give_engfuncs so that if game dll is
|
|
||||||
//plugin too and uses same method we get combined export table of plugin
|
|
||||||
//and game dll
|
|
||||||
if(!init_linkent_replacement(metamod_handle, GameDLL.handle)) {
|
|
||||||
META_WARNING("dll: Couldn't load linkent replacement for game DLL");
|
|
||||||
RETURN_ERRNO(mFALSE, ME_DLERROR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
META_WARNING("dll: Couldn't find GiveFnptrsToDll() in game DLL '%s': %s",
|
|
||||||
GameDLL.name, DLERROR());
|
|
||||||
RETURN_ERRNO(mFALSE, ME_DLMISSING);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Yes...another macro.
|
|
||||||
#define GET_FUNC_TABLE_FROM_GAME(gamedll, pfnGetFuncs, STR_GetFuncs, struct_field, API_TYPE, TABLE_TYPE, vers_pass, vers_int, vers_want, gotit) \
|
|
||||||
if((pfnGetFuncs = (API_TYPE) DLSYM(gamedll.handle, STR_GetFuncs))) { \
|
|
||||||
gamedll.funcs.struct_field = (TABLE_TYPE*) calloc(1, sizeof(TABLE_TYPE)); \
|
|
||||||
if(!gamedll.funcs.struct_field) {\
|
|
||||||
META_WARNING("malloc failed for gamedll struct_field: %s", STR_GetFuncs); \
|
|
||||||
} \
|
|
||||||
else if(pfnGetFuncs(gamedll.funcs.struct_field, vers_pass)) { \
|
|
||||||
META_DEBUG(3, ("dll: Game '%s': Found %s", gamedll.name, STR_GetFuncs)); \
|
|
||||||
gotit=1; \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
META_WARNING("dll: Failure calling %s in game '%s'", STR_GetFuncs, gamedll.name); \
|
|
||||||
free(gamedll.funcs.struct_field); \
|
|
||||||
gamedll.funcs.struct_field=NULL; \
|
|
||||||
if(vers_int != vers_want) { \
|
|
||||||
META_WARNING("dll: Interface version didn't match; we wanted %d, they had %d", vers_want, vers_int); \
|
|
||||||
/* reproduce error from engine */ \
|
|
||||||
META_CONS("=================="); \
|
|
||||||
META_CONS("Game DLL version mismatch"); \
|
|
||||||
META_CONS("DLL version is %d, engine version is %d", vers_int, vers_want); \
|
|
||||||
if(vers_int > vers_want) \
|
|
||||||
META_CONS("Engine appears to be outdated, check for updates"); \
|
|
||||||
else \
|
|
||||||
META_CONS("The game DLL for %s appears to be outdated, check for updates", GameDLL.name); \
|
|
||||||
META_CONS("=================="); \
|
|
||||||
ALERT(at_error, "Exiting...\n"); \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
else { \
|
|
||||||
META_DEBUG(5, ("dll: Game '%s': No %s", gamedll.name, STR_GetFuncs)); \
|
|
||||||
gamedll.funcs.struct_field=NULL; \
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for API-NEW interface in Game dll. We do this before API2/API, because
|
|
||||||
// that's what the engine appears to do..
|
|
||||||
iface_vers=NEW_DLL_FUNCTIONS_VERSION;
|
|
||||||
GET_FUNC_TABLE_FROM_GAME(GameDLL, pfn_getapinew, "GetNewDLLFunctions", newapi_table,
|
|
||||||
GETNEWDLLFUNCTIONS_FN, meta_new_dll_functions_t,
|
|
||||||
&iface_vers, iface_vers, NEW_DLL_FUNCTIONS_VERSION, found);
|
|
||||||
|
|
||||||
// Look for API2 interface in plugin; preferred over API-1.
|
|
||||||
found=0;
|
|
||||||
iface_vers=INTERFACE_VERSION;
|
|
||||||
GET_FUNC_TABLE_FROM_GAME(GameDLL, pfn_getapi2, "GetEntityAPI2", dllapi_table,
|
|
||||||
GETENTITYAPI2_FN, DLL_FUNCTIONS,
|
|
||||||
&iface_vers, iface_vers, INTERFACE_VERSION, found);
|
|
||||||
|
|
||||||
// Look for API-1 in plugin, if API2 interface wasn't found.
|
|
||||||
if(!found) {
|
|
||||||
found=0;
|
|
||||||
GET_FUNC_TABLE_FROM_GAME(GameDLL, pfn_getapi, "GetEntityAPI", dllapi_table,
|
|
||||||
GETENTITYAPI_FN, DLL_FUNCTIONS,
|
|
||||||
INTERFACE_VERSION, INTERFACE_VERSION, INTERFACE_VERSION, found);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If didn't find either, return failure.
|
|
||||||
if(!found) {
|
|
||||||
META_WARNING("dll: Couldn't find either GetEntityAPI nor GetEntityAPI2 in game DLL '%s'", GameDLL.name);
|
|
||||||
RETURN_ERRNO(mFALSE, ME_DLMISSING);
|
|
||||||
}
|
|
||||||
|
|
||||||
META_LOG("Game DLL for '%s' loaded successfully", GameDLL.desc);
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
LIBRARY metamod
|
|
||||||
EXPORTS
|
|
||||||
GiveFnptrsToDll @1
|
|
||||||
SECTIONS
|
|
||||||
.data READ WRITE
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
|
||||||
# Visual Studio 2005
|
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "metamod", "metamod.vcproj", "{02832A39-E902-46B7-8D47-911C37CF41B0}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Win32 = Debug|Win32
|
|
||||||
Release|Win32 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{02832A39-E902-46B7-8D47-911C37CF41B0}.Debug|Win32.ActiveCfg = Debug|Win32
|
|
||||||
{02832A39-E902-46B7-8D47-911C37CF41B0}.Debug|Win32.Build.0 = Debug|Win32
|
|
||||||
{02832A39-E902-46B7-8D47-911C37CF41B0}.Release|Win32.ActiveCfg = Release|Win32
|
|
||||||
{02832A39-E902-46B7-8D47-911C37CF41B0}.Release|Win32.Build.0 = Release|Win32
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
@@ -1,489 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="Windows-1252"?>
|
|
||||||
<VisualStudioProject
|
|
||||||
ProjectType="Visual C++"
|
|
||||||
Version="8,00"
|
|
||||||
Name="metamod"
|
|
||||||
ProjectGUID="{02832A39-E902-46B7-8D47-911C37CF41B0}"
|
|
||||||
RootNamespace="metamod"
|
|
||||||
Keyword="Win32Proj"
|
|
||||||
>
|
|
||||||
<Platforms>
|
|
||||||
<Platform
|
|
||||||
Name="Win32"
|
|
||||||
/>
|
|
||||||
</Platforms>
|
|
||||||
<ToolFiles>
|
|
||||||
</ToolFiles>
|
|
||||||
<Configurations>
|
|
||||||
<Configuration
|
|
||||||
Name="Debug|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="2"
|
|
||||||
CharacterSet="0"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
Optimization="0"
|
|
||||||
AdditionalIncludeDirectories="../../hlsdk/common ../../hlsdk/dlls ../../hlsdk/engine ../../hlsdk/pm_shared"
|
|
||||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;METAMOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;__METAMOD_BUILD__"
|
|
||||||
MinimalRebuild="true"
|
|
||||||
BasicRuntimeChecks="3"
|
|
||||||
RuntimeLibrary="3"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
Detect64BitPortabilityProblems="false"
|
|
||||||
DebugInformationFormat="4"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
LinkIncremental="2"
|
|
||||||
ModuleDefinitionFile="metamod.def"
|
|
||||||
GenerateDebugInformation="true"
|
|
||||||
SubSystem="2"
|
|
||||||
TargetMachine="1"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManifestTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAppVerifierTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
<Configuration
|
|
||||||
Name="Release|Win32"
|
|
||||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
|
||||||
IntermediateDirectory="$(ConfigurationName)"
|
|
||||||
ConfigurationType="2"
|
|
||||||
CharacterSet="0"
|
|
||||||
WholeProgramOptimization="1"
|
|
||||||
>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreBuildEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCustomBuildTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXMLDataGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebServiceProxyGeneratorTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCMIDLTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCCLCompilerTool"
|
|
||||||
AdditionalIncludeDirectories="..\hlsdk\common;..\hlsdk\dlls;..\hlsdk\engine;..\hlsdk\pm_shared;."
|
|
||||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;METAMOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;__METAMOD_BUILD__"
|
|
||||||
RuntimeLibrary="2"
|
|
||||||
UsePrecompiledHeader="0"
|
|
||||||
WarningLevel="3"
|
|
||||||
Detect64BitPortabilityProblems="false"
|
|
||||||
DebugInformationFormat="0"
|
|
||||||
CompileAs="0"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManagedResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCResourceCompilerTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPreLinkEventTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCLinkerTool"
|
|
||||||
LinkIncremental="1"
|
|
||||||
GenerateDebugInformation="false"
|
|
||||||
SubSystem="2"
|
|
||||||
OptimizeReferences="2"
|
|
||||||
EnableCOMDATFolding="2"
|
|
||||||
TargetMachine="1"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCALinkTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCManifestTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCXDCMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCBscMakeTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCFxCopTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCAppVerifierTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCWebDeploymentTool"
|
|
||||||
/>
|
|
||||||
<Tool
|
|
||||||
Name="VCPostBuildEventTool"
|
|
||||||
/>
|
|
||||||
</Configuration>
|
|
||||||
</Configurations>
|
|
||||||
<References>
|
|
||||||
</References>
|
|
||||||
<Files>
|
|
||||||
<Filter
|
|
||||||
Name="Source Files"
|
|
||||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
|
||||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
|
||||||
>
|
|
||||||
<File
|
|
||||||
RelativePath=".\api_hook.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\api_info.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\commands_meta.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\conf_meta.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\dllapi.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\engine_api.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\engineinfo.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\game_autodetect.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\game_support.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\h_export.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\linkgame.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\linkplug.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\log_meta.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\meta_eiface.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\metamod.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mhook.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mlist.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mplayer.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mplugin.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mqueue.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mreg.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mutil.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\osdep.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\osdep_detect_gamedll_win32.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\osdep_linkent_win32.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\osdep_p.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\reg_support.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\sdk_util.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\studioapi.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\support_meta.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\thread_logparse.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\vdate.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="Header Files"
|
|
||||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
|
||||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
|
||||||
>
|
|
||||||
<File
|
|
||||||
RelativePath=".\api_hook.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\api_info.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\commands_meta.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\comp_dep.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\conf_meta.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\dllapi.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\engine_api.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\engineinfo.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\game_autodetect.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\game_support.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\games.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\h_export.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\info_name.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\linkent.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\log_meta.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\meta_api.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\meta_eiface.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\metamod.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mhook.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mlist.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mm_pextensions.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mplayer.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mplugin.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mqueue.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mreg.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\mutil.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\new_baseclass.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\osdep.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\osdep_p.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\plinfo.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\reg_support.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\ret_type.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\sdk_util.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\studioapi.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\support_meta.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\thread_logparse.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\tqueue.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\types_meta.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\vdate.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
|
||||||
RelativePath=".\vers_meta.h"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
<Filter
|
|
||||||
Name="Resource Files"
|
|
||||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
|
||||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
|
||||||
>
|
|
||||||
<File
|
|
||||||
RelativePath=".\res_meta.rc"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
</Filter>
|
|
||||||
</Files>
|
|
||||||
<Globals>
|
|
||||||
</Globals>
|
|
||||||
</VisualStudioProject>
|
|
||||||
@@ -1,901 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// mlist.cpp - functions for list of plugins (class MPluginList)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h> // errno, etc
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "mlist.h" // me
|
|
||||||
#include "mplugin.h" // class MPlugin
|
|
||||||
#include "plinfo.h" // plid_t, etc
|
|
||||||
#include "commands_meta.h" // cmd_meta_pluginlist, etc
|
|
||||||
#include "metamod.h" // GameDLL, etc
|
|
||||||
#include "types_meta.h" // mBOOL
|
|
||||||
#include "log_meta.h" // META_LOG, etc
|
|
||||||
#include "osdep.h" // win32 snprintf, normalize_pathname,
|
|
||||||
#include "osdep_p.h"
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
MPluginList::MPluginList(const char *ifile)
|
|
||||||
: size(MAX_PLUGINS), endlist(0)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
// store filename of ini file
|
|
||||||
STRNCPY(inifile, ifile, sizeof(inifile));
|
|
||||||
// initialize array
|
|
||||||
for(i=0; i < size; i++) {
|
|
||||||
//reset to empty
|
|
||||||
plist[i].index=i+1;
|
|
||||||
reset_plugin(&plist[i]);
|
|
||||||
}
|
|
||||||
endlist=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resets plugin to empty
|
|
||||||
void DLLINTERNAL MPluginList::reset_plugin(MPlugin *pl_find) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
//calculate index
|
|
||||||
i = pl_find - &plist[0];
|
|
||||||
|
|
||||||
//free any pointers first
|
|
||||||
pl_find->free_api_pointers();
|
|
||||||
|
|
||||||
//set zero
|
|
||||||
memset(pl_find, 0, sizeof(*pl_find));
|
|
||||||
|
|
||||||
pl_find->index=i+1; // 1-based
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find a plugin based on the plugin index #.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_ARGUMENT invalid pindex
|
|
||||||
// - ME_NOTFOUND couldn't find a matching plugin
|
|
||||||
MPlugin * DLLINTERNAL MPluginList::find(int pindex) {
|
|
||||||
MPlugin *pfound;
|
|
||||||
if(pindex <= 0)
|
|
||||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
|
||||||
pfound=&plist[pindex-1];
|
|
||||||
if(pfound->status < PL_VALID)
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
else
|
|
||||||
return(pfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find a plugin based on the plugin handle.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_ARGUMENT invalid pindex
|
|
||||||
// - ME_NOTFOUND couldn't find a matching plugin
|
|
||||||
MPlugin * DLLINTERNAL MPluginList::find(DLHANDLE handle) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if(!handle)
|
|
||||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
if(plist[i].status < PL_VALID)
|
|
||||||
continue;
|
|
||||||
if(plist[i].handle == handle)
|
|
||||||
return(&plist[i]);
|
|
||||||
}
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear source_plugin_index on all matching plugins
|
|
||||||
void DLLINTERNAL MPluginList::clear_source_plugin_index(int source_index) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if(source_index <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
if(plist[i].status < PL_VALID)
|
|
||||||
continue;
|
|
||||||
if(plist[i].source_plugin_index == source_index)
|
|
||||||
plist[i].source_plugin_index = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find if any plugin has been loaded by plugin 'source_index'
|
|
||||||
mBOOL DLLINTERNAL MPluginList::found_child_plugins(int source_index) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if(source_index <= 0)
|
|
||||||
return(mFALSE);
|
|
||||||
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
if(plist[i].status < PL_VALID)
|
|
||||||
continue;
|
|
||||||
if(plist[i].source_plugin_index == source_index)
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try make endlist lower (called after plugin unload)
|
|
||||||
void DLLINTERNAL MPluginList::trim_list(void) {
|
|
||||||
int i,n;
|
|
||||||
|
|
||||||
if(endlist <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for(i=0,n=0; i < endlist; i++) {
|
|
||||||
if(plist[i].status == PL_EMPTY)
|
|
||||||
continue;
|
|
||||||
n=i+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(n < endlist)
|
|
||||||
endlist=n;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find a plugin with the given plid.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_ARGUMENT null plid_t
|
|
||||||
// - ME_NOTFOUND couldn't find a matching plugin
|
|
||||||
MPlugin * DLLINTERNAL MPluginList::find(plid_t id) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if(!id)
|
|
||||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
if(plist[i].status < PL_VALID)
|
|
||||||
continue;
|
|
||||||
if(plist[i].info == id)
|
|
||||||
return(&plist[i]);
|
|
||||||
}
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find a plugin with the given pathname.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_ARGUMENT null path
|
|
||||||
// - ME_NOTFOUND couldn't find a matching plugin
|
|
||||||
MPlugin * DLLINTERNAL MPluginList::find(const char *findpath) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if(!findpath)
|
|
||||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
|
||||||
META_DEBUG(8, ("Looking for loaded plugin with dlfnamepath: %s", findpath));
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
META_DEBUG(9, ("Looking at: plugin %s loadedpath: %s", plist[i].file, plist[i].pathname));
|
|
||||||
if(plist[i].status < PL_VALID)
|
|
||||||
continue;
|
|
||||||
if(strmatch(plist[i].pathname, findpath)) {
|
|
||||||
META_DEBUG(8, ("Found loaded plugin %s", plist[i].file));
|
|
||||||
return(&plist[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
META_DEBUG(8, ("No loaded plugin found with path: %s", findpath));
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find a plugin that uses the given memory location.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_ARGUMENT null memptr
|
|
||||||
// - ME_NOTFOUND couldn't find a matching plugin
|
|
||||||
// - errno's from DLFNAME()
|
|
||||||
MPlugin * DLLINTERNAL MPluginList::find_memloc(void *memptr) {
|
|
||||||
#ifdef linux
|
|
||||||
const char *dlfile;
|
|
||||||
|
|
||||||
if(!memptr)
|
|
||||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
|
||||||
if(!(dlfile=DLFNAME(memptr))) {
|
|
||||||
META_DEBUG(8, ("DLFNAME failed to find memloc %d", memptr));
|
|
||||||
// meta_errno should be already set in DLFNAME
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(find(dlfile));
|
|
||||||
#else
|
|
||||||
DLHANDLE dlhandle;
|
|
||||||
|
|
||||||
if(!memptr)
|
|
||||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
|
||||||
if(!(dlhandle=get_module_handle_of_memptr(memptr))) {
|
|
||||||
META_DEBUG(8, ("DLFNAME failed to find memloc %d", memptr));
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(find(dlhandle));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find a plugin with non-ambiguous prefix string matching desc, file,
|
|
||||||
// name, or logtag.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_ARGUMENT null prefix
|
|
||||||
// - ME_NOTFOUND couldn't find a matching plugin
|
|
||||||
// - ME_NOTUNIQ found multiple matches; no unique match
|
|
||||||
MPlugin * DLLINTERNAL MPluginList::find_match(const char *prefix) {
|
|
||||||
int i, len;
|
|
||||||
MPlugin *iplug, *pfound;
|
|
||||||
char buf[NAME_MAX];
|
|
||||||
|
|
||||||
if(!prefix)
|
|
||||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
|
||||||
pfound=NULL;
|
|
||||||
len=strlen(prefix);
|
|
||||||
safevoid_snprintf(buf, sizeof(buf), "mm_%s", prefix);
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
iplug=&plist[i];
|
|
||||||
if(iplug->status < PL_VALID)
|
|
||||||
continue;
|
|
||||||
if(iplug->info && strncasecmp(iplug->info->name, prefix, len) == 0) {
|
|
||||||
if(pfound)
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
|
||||||
pfound=iplug;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if(strncasecmp(iplug->desc, prefix, len) == 0) {
|
|
||||||
if(pfound)
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
|
||||||
pfound=iplug;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if(strncasecmp(iplug->file, prefix, len) == 0) {
|
|
||||||
if(pfound)
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
|
||||||
pfound=iplug;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if(strncasecmp(iplug->file, buf, strlen(buf)) == 0) {
|
|
||||||
if(pfound)
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
|
||||||
pfound=iplug;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else if(iplug->info
|
|
||||||
&& strncasecmp(iplug->info->logtag, prefix, len) == 0)
|
|
||||||
{
|
|
||||||
if(pfound)
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
|
||||||
pfound=iplug;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pfound)
|
|
||||||
return(pfound);
|
|
||||||
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find a plugin with same file, logtag, desc or significant
|
|
||||||
// prefix of file. Uses the platform_match() method of MPlugin.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_ARGUMENT null prefix
|
|
||||||
// - ME_NOTFOUND couldn't find a matching plugin
|
|
||||||
MPlugin * DLLINTERNAL MPluginList::find_match(MPlugin *pmatch) {
|
|
||||||
int i;
|
|
||||||
MPlugin *iplug, *pfound;
|
|
||||||
if(!pmatch)
|
|
||||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
|
||||||
pfound=NULL;
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
iplug=&plist[i];
|
|
||||||
if(pmatch->platform_match(iplug)) {
|
|
||||||
pfound=iplug;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pfound)
|
|
||||||
return(pfound);
|
|
||||||
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a plugin to the list.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_MAXREACHED reached max plugins
|
|
||||||
MPlugin * DLLINTERNAL MPluginList::add(MPlugin *padd) {
|
|
||||||
int i;
|
|
||||||
MPlugin *iplug;
|
|
||||||
|
|
||||||
// Find either:
|
|
||||||
// - a slot in the list that's not being used
|
|
||||||
// - the end of the list
|
|
||||||
for(i=0; i < endlist && plist[i].status != PL_EMPTY; i++);
|
|
||||||
|
|
||||||
// couldn't find a slot to use
|
|
||||||
if(i==size) {
|
|
||||||
META_WARNING("Couldn't add plugin '%s' to list; reached max plugins (%d)",
|
|
||||||
padd->file, i);
|
|
||||||
RETURN_ERRNO(NULL, ME_MAXREACHED);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we found the end of the list, advance end marker
|
|
||||||
if(i==endlist)
|
|
||||||
endlist++;
|
|
||||||
iplug = &plist[i];
|
|
||||||
|
|
||||||
// copy filename into this free slot
|
|
||||||
STRNCPY(iplug->filename, padd->filename, sizeof(iplug->filename));
|
|
||||||
// Copy file offset ptr.
|
|
||||||
// Can't just copy ptr, as it points to offset in padd, which will go
|
|
||||||
// away; need to point to corresponding offset in iplug.
|
|
||||||
iplug->file = iplug->filename + (padd->file - padd->filename);
|
|
||||||
// copy description
|
|
||||||
STRNCPY(iplug->desc, padd->desc, sizeof(iplug->desc));
|
|
||||||
// copy pathname
|
|
||||||
STRNCPY(iplug->pathname, padd->pathname, sizeof(iplug->pathname));
|
|
||||||
// copy source
|
|
||||||
iplug->source=padd->source;
|
|
||||||
// copy loader-plugin
|
|
||||||
iplug->source_plugin_index=padd->source_plugin_index;
|
|
||||||
// copy status
|
|
||||||
iplug->status=padd->status;
|
|
||||||
|
|
||||||
return(iplug);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Read plugins.ini at server startup.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_NOFILE ini file missing or empty
|
|
||||||
mBOOL DLLINTERNAL MPluginList::ini_startup() {
|
|
||||||
FILE *fp;
|
|
||||||
char line[MAX_STRBUF_LEN];
|
|
||||||
int n, ln;
|
|
||||||
MPlugin *pmatch;
|
|
||||||
|
|
||||||
if(!valid_gamedir_file(inifile)) {
|
|
||||||
META_WARNING("ini: Metamod plugins file empty or missing: %s", inifile);
|
|
||||||
RETURN_ERRNO(mFALSE, ME_NOFILE);
|
|
||||||
}
|
|
||||||
full_gamedir_path(inifile, inifile);
|
|
||||||
|
|
||||||
fp=fopen(inifile, "r");
|
|
||||||
if(!fp) {
|
|
||||||
META_WARNING("ini: Unable to open plugins file '%s': %s", inifile,
|
|
||||||
strerror(errno));
|
|
||||||
RETURN_ERRNO(mFALSE, ME_NOFILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
META_LOG("ini: Begin reading plugins list: %s", inifile);
|
|
||||||
for(n=0, ln=1; !feof(fp) && fgets(line, sizeof(line), fp) && n < size; ln++) {
|
|
||||||
// Remove line terminations.
|
|
||||||
char *cp;
|
|
||||||
if((cp=strrchr(line, '\r')))
|
|
||||||
*cp='\0';
|
|
||||||
if((cp=strrchr(line, '\n')))
|
|
||||||
*cp='\0';
|
|
||||||
// Parse directly into next entry in array
|
|
||||||
if(!plist[n].ini_parseline(line)) {
|
|
||||||
if(meta_errno==ME_FORMAT)
|
|
||||||
META_WARNING("ini: Skipping malformed line %d of %s", ln,
|
|
||||||
inifile);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Check for a duplicate - an existing entry with this pathname.
|
|
||||||
if(find(plist[n].pathname)) {
|
|
||||||
// Should we check platform specific level here?
|
|
||||||
META_INFO("ini: Skipping duplicate plugin, line %d of %s: %s",
|
|
||||||
ln, inifile, plist[n].pathname);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Check for a matching platform with different platform specifics
|
|
||||||
// level.
|
|
||||||
if(NULL != (pmatch=find_match(&plist[n]))) {
|
|
||||||
if(pmatch->pfspecific >= plist[n].pfspecific) {
|
|
||||||
META_DEBUG(1, ("ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)",
|
|
||||||
ln, inifile, pmatch->pfspecific, plist[n].pfspecific));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
META_DEBUG(1, ("ini: Plugin in line %d overrides existing plugin with lower platform specific level %d, ours %d",
|
|
||||||
ln, pmatch->pfspecific, plist[n].pfspecific));
|
|
||||||
//reset to empty
|
|
||||||
reset_plugin(pmatch);
|
|
||||||
}
|
|
||||||
plist[n].action=PA_LOAD;
|
|
||||||
META_LOG("ini: Read plugin config for: %s", plist[n].desc);
|
|
||||||
n++;
|
|
||||||
endlist=n; // mark end of list
|
|
||||||
}
|
|
||||||
META_LOG("ini: Finished reading plugins list: %s; Found %d plugins to load",
|
|
||||||
inifile, n);
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
if(!n) {
|
|
||||||
META_WARNING("ini: Warning; no plugins found to load?");
|
|
||||||
}
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-read plugins.ini looking for added/deleted/changed plugins.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_NOFILE ini file missing or empty
|
|
||||||
mBOOL DLLINTERNAL MPluginList::ini_refresh() {
|
|
||||||
FILE *fp;
|
|
||||||
char line[MAX_STRBUF_LEN];
|
|
||||||
int n, ln;
|
|
||||||
MPlugin pl_temp;
|
|
||||||
MPlugin *pl_found, *pl_added;
|
|
||||||
|
|
||||||
fp=fopen(inifile, "r");
|
|
||||||
if(!fp) {
|
|
||||||
META_WARNING("ini: Unable to open plugins file '%s': %s", inifile,
|
|
||||||
strerror(errno));
|
|
||||||
RETURN_ERRNO(mFALSE, ME_NOFILE);
|
|
||||||
}
|
|
||||||
|
|
||||||
META_LOG("ini: Begin re-reading plugins list: %s", inifile);
|
|
||||||
for(n=0, ln=1; !feof(fp) && fgets(line, sizeof(line), fp) && n < size; ln++)
|
|
||||||
{
|
|
||||||
// Remove line terminations.
|
|
||||||
char *cp;
|
|
||||||
if((cp=strrchr(line, '\r')))
|
|
||||||
*cp='\0';
|
|
||||||
if((cp=strrchr(line, '\n')))
|
|
||||||
*cp='\0';
|
|
||||||
// Parse into a temp plugin
|
|
||||||
memset(&pl_temp, 0, sizeof(pl_temp));
|
|
||||||
if(!pl_temp.ini_parseline(line)) {
|
|
||||||
if(meta_errno==ME_FORMAT)
|
|
||||||
META_WARNING("ini: Skipping malformed line %d of %s",
|
|
||||||
ln, inifile);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Try to find plugin with this pathname in the current list of
|
|
||||||
// plugins.
|
|
||||||
if(!(pl_found=find(pl_temp.pathname))) {
|
|
||||||
// Check for a matching platform with higher platform specifics
|
|
||||||
// level.
|
|
||||||
if(NULL != (pl_found=find_match(&pl_temp))) {
|
|
||||||
if(pl_found->pfspecific >= pl_temp.pfspecific) {
|
|
||||||
META_DEBUG(1, ("ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)",
|
|
||||||
ln, inifile, pl_found->pfspecific, pl_temp.pfspecific));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(PA_LOAD == pl_found->action) {
|
|
||||||
META_DEBUG(1, ("ini: Plugin in line %d overrides loading of plugin with lower platform specific level %d, ours %d",
|
|
||||||
ln, pl_found->pfspecific, pl_temp.pfspecific));
|
|
||||||
//reset to empty
|
|
||||||
reset_plugin(pl_found);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
META_DEBUG(1, ("ini: Plugin in line %d should override existing plugin with lower platform specific level %d, ours %d. Unable to comply.",
|
|
||||||
ln, pl_found->pfspecific, pl_temp.pfspecific));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// new plugin; add to list
|
|
||||||
if((pl_added=add(&pl_temp))) {
|
|
||||||
// try to load this plugin at the next opportunity
|
|
||||||
pl_added->action=PA_LOAD;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
// error details logged in add()
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// This plugin is already in the current list of plugins.
|
|
||||||
// Pathname already matches. Recopy desc, if specified in
|
|
||||||
// plugins.ini.
|
|
||||||
if(pl_temp.desc[0] != '<')
|
|
||||||
STRNCPY(pl_found->desc, pl_temp.desc, sizeof(pl_found->desc));
|
|
||||||
|
|
||||||
// Check the file to see if it looks like it's been modified
|
|
||||||
// since we last loaded it.
|
|
||||||
if(!pl_found->newer_file()) {
|
|
||||||
if(meta_errno==ME_NOFILE) {
|
|
||||||
META_WARNING("ini: Skipping plugin, couldn't stat file '%s': %s",
|
|
||||||
pl_found->pathname, strerror(errno));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// File hasn't been updated.
|
|
||||||
// Keep plugin (don't let refresh() unload it).
|
|
||||||
pl_found->action=PA_KEEP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Newer file on disk.
|
|
||||||
else if(pl_found->status >= PL_OPENED) {
|
|
||||||
META_DEBUG(2, ("ini: Plugin '%s' has newer file on disk", pl_found->desc));
|
|
||||||
pl_found->action=PA_RELOAD;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
META_WARNING("ini: Plugin '%s' has newer file, but unexpected status (%s)",
|
|
||||||
pl_found->desc, pl_found->str_status());
|
|
||||||
}
|
|
||||||
if(NULL != pl_found) {
|
|
||||||
META_LOG("ini: Read plugin config for: %s", pl_found->desc);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
META_LOG("ini: Read plugin config for: %s", pl_temp.desc);
|
|
||||||
}
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
META_LOG("ini: Finished reading plugins list: %s; Found %d plugins", inifile, n);
|
|
||||||
|
|
||||||
fclose(fp);
|
|
||||||
if(!n) {
|
|
||||||
META_WARNING("ini: Warning; no plugins found to load?");
|
|
||||||
}
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load a plugin from plugin request.
|
|
||||||
// meta_errno values:
|
|
||||||
// - errno's from resolve()
|
|
||||||
// - ME_ALREADY this plugin already loaded
|
|
||||||
// - errno's from add()
|
|
||||||
// - errno's from load()
|
|
||||||
MPlugin * DLLINTERNAL MPluginList::plugin_addload(plid_t plid, const char *fname, PLUG_LOADTIME now) {
|
|
||||||
MPlugin pl_temp;
|
|
||||||
MPlugin *pl_found, *pl_added, *pl_loader;
|
|
||||||
|
|
||||||
// Find loader plugin
|
|
||||||
if(!(pl_loader=find(plid))) {
|
|
||||||
// Couldn't find a matching file on disk
|
|
||||||
META_DEBUG(1, ("Couldn't find plugin that gave this loading request!"));
|
|
||||||
// meta_errno should be already set in resolve()
|
|
||||||
RETURN_ERRNO(NULL, ME_BADREQ);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&pl_temp, 0, sizeof(pl_temp));
|
|
||||||
|
|
||||||
// copy filename
|
|
||||||
if(!pl_temp.plugin_parseline(fname, pl_loader->index)) {
|
|
||||||
// parse_plugin_load doesn't return mFALSE.
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolve given path into a file; accepts various "shortcut"
|
|
||||||
// pathnames.
|
|
||||||
if(pl_temp.resolve() != mTRUE) {
|
|
||||||
// Couldn't find a matching file on disk
|
|
||||||
META_DEBUG(1, ("Couldn't resolve given path into a file: %s", pl_temp.file));
|
|
||||||
// meta_errno should be already set in resolve()
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to find plugin with this pathname in the current list of
|
|
||||||
// plugins.
|
|
||||||
if((pl_found=find(pl_temp.pathname))) {
|
|
||||||
// Already in list
|
|
||||||
META_DEBUG(1, ("Plugin '%s' already in current list; file=%s desc='%s'",
|
|
||||||
pl_temp.file, pl_found->file, pl_found->desc));
|
|
||||||
RETURN_ERRNO(NULL, ME_ALREADY);
|
|
||||||
}
|
|
||||||
// new plugin; add to list
|
|
||||||
if(!(pl_added=add(&pl_temp))) {
|
|
||||||
META_DEBUG(1, ("Couldn't add plugin '%s' to list; see log", pl_temp.desc));
|
|
||||||
// meta_errno should be already set in add()
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to load new plugin (setting 'must load now')
|
|
||||||
pl_added->action=PA_LOAD;
|
|
||||||
if(!pl_added->load(now)) {
|
|
||||||
// load failed
|
|
||||||
if(meta_errno==ME_NOTALLOWED || meta_errno==ME_DELAYED) {
|
|
||||||
META_DEBUG(1, ("Plugin '%s' couldn't attach; only allowed %s",
|
|
||||||
pl_added->desc, pl_added->str_loadable(SL_ALLOWED)));
|
|
||||||
pl_added->clear();
|
|
||||||
}
|
|
||||||
else if(pl_added->status == PL_OPENED)
|
|
||||||
META_DEBUG(1, ("Opened plugin '%s', but failed to attach; see log", pl_added->desc));
|
|
||||||
else
|
|
||||||
META_DEBUG(1, ("Couldn't load plugin '%s'; see log", pl_added->desc));
|
|
||||||
// meta_errno should be already set in load()
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
META_DEBUG(1, ("Loaded plugin '%s' successfully", pl_added->desc));
|
|
||||||
meta_errno = ME_NOERROR;
|
|
||||||
return(pl_added);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load a plugin from a console command.
|
|
||||||
// meta_errno values:
|
|
||||||
// - errno's from cmd_parseline()
|
|
||||||
// - errno's from resolve()
|
|
||||||
// - ME_ALREADY this plugin already loaded
|
|
||||||
// - errno's from add()
|
|
||||||
// - errno's from load()
|
|
||||||
mBOOL DLLINTERNAL MPluginList::cmd_addload(const char *args) {
|
|
||||||
MPlugin pl_temp;
|
|
||||||
MPlugin *pl_found, *pl_added;
|
|
||||||
|
|
||||||
memset(&pl_temp, 0, sizeof(pl_temp));
|
|
||||||
|
|
||||||
// XXX move back to comands_meta ?
|
|
||||||
|
|
||||||
// parse into a temp plugin
|
|
||||||
if(pl_temp.cmd_parseline(args) != mTRUE) {
|
|
||||||
META_CONS("Couldn't parse 'meta load' arguments: %s", args);
|
|
||||||
// meta_errno should be already set in cmd_parseline()
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// resolve given path into a file; accepts various "shortcut"
|
|
||||||
// pathnames.
|
|
||||||
if(pl_temp.resolve() != mTRUE) {
|
|
||||||
// Couldn't find a matching file on disk
|
|
||||||
META_CONS("Couldn't resolve given path into a file: %s",
|
|
||||||
pl_temp.file);
|
|
||||||
// meta_errno should be already set in resolve()
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to find plugin with this pathname in the current list of
|
|
||||||
// plugins.
|
|
||||||
if((pl_found=find(pl_temp.pathname))) {
|
|
||||||
// Already in list
|
|
||||||
META_CONS("Plugin '%s' already in current list; file=%s desc='%s'",
|
|
||||||
pl_temp.file, pl_found->file, pl_found->desc);
|
|
||||||
RETURN_ERRNO(mFALSE, ME_ALREADY);
|
|
||||||
}
|
|
||||||
// new plugin; add to list
|
|
||||||
if(!(pl_added=add(&pl_temp))) {
|
|
||||||
META_CONS("Couldn't add plugin '%s' to list; see log", pl_temp.desc);
|
|
||||||
// meta_errno should be already set in add()
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to load new plugin
|
|
||||||
pl_added->action=PA_LOAD;
|
|
||||||
if(!pl_added->load(PT_ANYTIME)) {
|
|
||||||
// load failed
|
|
||||||
if(meta_errno==ME_DELAYED)
|
|
||||||
META_CONS("Loaded plugin '%s', but will wait to become active, %s",
|
|
||||||
pl_added->desc, pl_added->str_loadable(SL_ALLOWED));
|
|
||||||
else if(meta_errno==ME_NOTALLOWED) {
|
|
||||||
META_CONS("Plugin '%s' couldn't attach; only allowed %s",
|
|
||||||
pl_added->desc, pl_added->str_loadable(SL_ALLOWED));
|
|
||||||
pl_added->clear();
|
|
||||||
}
|
|
||||||
else if(pl_added->status == PL_OPENED)
|
|
||||||
META_CONS("Opened plugin '%s', but failed to attach; see log", pl_added->desc);
|
|
||||||
else
|
|
||||||
META_CONS("Couldn't load plugin '%s'; see log", pl_added->desc);
|
|
||||||
show();
|
|
||||||
// meta_errno should be already set in load()
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
META_CONS("Loaded plugin '%s' successfully", pl_added->desc);
|
|
||||||
show();
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load plugins at startup.
|
|
||||||
// meta_errno values:
|
|
||||||
// - errno's from ini_startup()
|
|
||||||
mBOOL DLLINTERNAL MPluginList::load() {
|
|
||||||
int i, n;
|
|
||||||
|
|
||||||
if(!ini_startup()) {
|
|
||||||
META_WARNING("Problem loading plugins.ini: %s", inifile);
|
|
||||||
// meta_errno should be already set in ini_startup()
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
META_LOG("dll: Loading plugins...");
|
|
||||||
for(i=0, n=0; i < endlist; i++) {
|
|
||||||
if(plist[i].status < PL_VALID)
|
|
||||||
continue;
|
|
||||||
if(plist[i].load(PT_STARTUP) == mTRUE)
|
|
||||||
n++;
|
|
||||||
else
|
|
||||||
// all plugins should be loadable at startup...
|
|
||||||
META_WARNING("dll: Failed to load plugin '%s'", plist[i].file);
|
|
||||||
}
|
|
||||||
META_LOG("dll: Finished loading %d plugins", n);
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update list of loaded plugins from ini file, and load any new/changed plugins.
|
|
||||||
// meta_errno values:
|
|
||||||
// - errno's from ini_refresh()
|
|
||||||
mBOOL DLLINTERNAL MPluginList::refresh(PLUG_LOADTIME now) {
|
|
||||||
int i, ndone=0, nkept=0, nloaded=0, nunloaded=0, nreloaded=0, ndelayed=0;
|
|
||||||
MPlugin *iplug;
|
|
||||||
|
|
||||||
if(!ini_refresh()) {
|
|
||||||
META_WARNING("dll: Problem reloading plugins.ini: %s", inifile);
|
|
||||||
// meta_errno should be already set in ini_refresh()
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
META_LOG("dll: Updating plugins...");
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
iplug=&plist[i];
|
|
||||||
if(iplug->status < PL_VALID)
|
|
||||||
continue;
|
|
||||||
switch(iplug->action) {
|
|
||||||
case PA_KEEP:
|
|
||||||
META_DEBUG(1, ("Keeping plugin '%s'", iplug->desc));
|
|
||||||
iplug->action=PA_NONE;
|
|
||||||
nkept++;
|
|
||||||
break;
|
|
||||||
case PA_LOAD:
|
|
||||||
META_DEBUG(1, ("Loading plugin '%s'", iplug->desc));
|
|
||||||
if(iplug->load(now))
|
|
||||||
nloaded++;
|
|
||||||
else if(meta_errno==ME_DELAYED)
|
|
||||||
ndelayed++;
|
|
||||||
break;
|
|
||||||
case PA_RELOAD:
|
|
||||||
META_DEBUG(1, ("Reloading plugin '%s'", iplug->desc));
|
|
||||||
if(iplug->reload(now, PNL_FILE_NEWER))
|
|
||||||
nreloaded++;
|
|
||||||
else if(meta_errno==ME_DELAYED)
|
|
||||||
ndelayed++;
|
|
||||||
break;
|
|
||||||
case PA_NONE:
|
|
||||||
// If previously loaded from ini, but apparently removed from new ini.
|
|
||||||
if(iplug->source==PS_INI && iplug->status >= PL_RUNNING) {
|
|
||||||
META_DEBUG(1, ("Unloading plugin '%s'", iplug->desc));
|
|
||||||
iplug->action=PA_UNLOAD;
|
|
||||||
if(iplug->unload(now, PNL_INI_DELETED, PNL_INI_DELETED))
|
|
||||||
nunloaded++;
|
|
||||||
else if(meta_errno==ME_DELAYED)
|
|
||||||
ndelayed++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PA_ATTACH:
|
|
||||||
// Previously requested attach, but was delayed?
|
|
||||||
META_DEBUG(1, ("Retrying attach plugin '%s'", iplug->desc));
|
|
||||||
if(iplug->retry(now, PNL_DELAYED))
|
|
||||||
nloaded++;
|
|
||||||
else if(meta_errno==ME_DELAYED)
|
|
||||||
ndelayed++;
|
|
||||||
break;
|
|
||||||
case PA_UNLOAD:
|
|
||||||
// Previously requested unload, but was delayed?
|
|
||||||
META_DEBUG(1, ("Retrying unload plugin '%s'", iplug->desc));
|
|
||||||
if(iplug->retry(now, PNL_DELAYED))
|
|
||||||
nunloaded++;
|
|
||||||
else if(meta_errno==ME_DELAYED)
|
|
||||||
ndelayed++;
|
|
||||||
break;
|
|
||||||
case PA_NULL:
|
|
||||||
META_WARNING("dll: Unexpected action for plugin '%s': '%s'", iplug->desc, iplug->str_action());
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
META_WARNING("dll: Unrecognized action for plugin '%s': '%s'", iplug->desc, iplug->str_action());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ndone++;
|
|
||||||
}
|
|
||||||
META_LOG("dll: Finished updating %d plugins; kept %d, loaded %d, unloaded %d, reloaded %d, delayed %d",
|
|
||||||
ndone, nkept, nloaded, nunloaded, nreloaded, ndelayed);
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-enable any plugins currently paused.
|
|
||||||
// meta_errno values:
|
|
||||||
// - none
|
|
||||||
void DLLINTERNAL MPluginList::unpause_all(void) {
|
|
||||||
int i;
|
|
||||||
MPlugin *iplug;
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
iplug=&plist[i];
|
|
||||||
if(iplug->status==PL_PAUSED)
|
|
||||||
iplug->unpause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retry any pending actions on plugins, for instance load/unload delayed
|
|
||||||
// until changelevel.
|
|
||||||
// meta_errno values:
|
|
||||||
// - none
|
|
||||||
void DLLINTERNAL MPluginList::retry_all(PLUG_LOADTIME now) {
|
|
||||||
int i;
|
|
||||||
MPlugin *iplug;
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
iplug=&plist[i];
|
|
||||||
if(iplug->action != PA_NONE)
|
|
||||||
iplug->retry(now, PNL_DELAYED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// List plugins and information about them in a formatted table.
|
|
||||||
// meta_errno values:
|
|
||||||
// - none
|
|
||||||
void DLLINTERNAL MPluginList::show(int source_index) {
|
|
||||||
int i, n=0, r=0;
|
|
||||||
MPlugin *pl;
|
|
||||||
char desc[15+1], file[16+1], vers[7+1]; // plus 1 for term null
|
|
||||||
|
|
||||||
if(source_index <= 0)
|
|
||||||
META_CONS("Currently loaded plugins:");
|
|
||||||
else
|
|
||||||
META_CONS("Child plugins:");
|
|
||||||
|
|
||||||
META_CONS(" %*s %-*s %-4s %-4s %-*s v%-*s %-*s %-5s %-5s",
|
|
||||||
WIDTH_MAX_PLUGINS, "",
|
|
||||||
sizeof(desc)-1, "description",
|
|
||||||
"stat", "pend",
|
|
||||||
sizeof(file)-1, "file", sizeof(vers)-1, "ers",
|
|
||||||
2+WIDTH_MAX_PLUGINS, "src",
|
|
||||||
"load ", "unlod");
|
|
||||||
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
pl=&plist[i];
|
|
||||||
if(pl->status < PL_VALID)
|
|
||||||
continue;
|
|
||||||
if(source_index > 0 && pl->source_plugin_index != source_index)
|
|
||||||
continue;
|
|
||||||
STRNCPY(desc, pl->desc, sizeof(desc));
|
|
||||||
STRNCPY(file, pl->file, sizeof(file));
|
|
||||||
if(pl->info && pl->info->version)
|
|
||||||
STRNCPY(vers, pl->info->version, sizeof(vers));
|
|
||||||
else
|
|
||||||
STRNCPY(vers, " -", sizeof(vers));
|
|
||||||
META_CONS(" [%*d] %-*s %-4s %-4s %-*s v%-*s %-*s %-5s %-5s",
|
|
||||||
WIDTH_MAX_PLUGINS, pl->index,
|
|
||||||
sizeof(desc)-1, desc,
|
|
||||||
pl->str_status(ST_SHOW), pl->str_action(SA_SHOW),
|
|
||||||
sizeof(file)-1, file, sizeof(vers)-1, vers,
|
|
||||||
2+WIDTH_MAX_PLUGINS, pl->str_source(SO_SHOW),
|
|
||||||
pl->str_loadable(SL_SHOW), pl->str_unloadable(SL_SHOW));
|
|
||||||
if(pl->status == PL_RUNNING)
|
|
||||||
r++;
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
META_CONS("%d plugins, %d running", n, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
// List plugins and information to Player/client entity. Differs from the
|
|
||||||
// "meta list" console command in that:
|
|
||||||
// - Shows only "running" plugins, skipping any failed or paused plugins.
|
|
||||||
// - Limited info about each plugin, mostly the "public" info (name, author,
|
|
||||||
// etc).
|
|
||||||
// meta_errno values:
|
|
||||||
// - none
|
|
||||||
void DLLINTERNAL MPluginList::show_client(edict_t *pEntity) {
|
|
||||||
int i, n=0;
|
|
||||||
MPlugin *pl;
|
|
||||||
META_CLIENT(pEntity, "Currently running plugins:");
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
pl=&plist[i];
|
|
||||||
if(pl->status != PL_RUNNING || !pl->info)
|
|
||||||
continue;
|
|
||||||
n++;
|
|
||||||
META_CLIENT(pEntity, " [%3d] %s, v%s, %s, by %s, see %s",
|
|
||||||
n,
|
|
||||||
pl->info->name ? pl->info->name : "<unknown>",
|
|
||||||
pl->info->version ? pl->info->version : "<?>",
|
|
||||||
pl->info->date ? pl->info->date : "<../../..>",
|
|
||||||
pl->info->author ? pl->info->author : "<unknown>",
|
|
||||||
pl->info->url ? pl->info->url : "<unknown>");
|
|
||||||
}
|
|
||||||
META_CLIENT(pEntity, "%d plugins", n);
|
|
||||||
}
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// mplayer.cpp - methods of individual player (class MPlayer) and
|
|
||||||
// list of players (class MPlayerList).
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2005-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h> // strdup()
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "mplayer.h" // me
|
|
||||||
#include "sdk_util.h" // ENTINDEX()
|
|
||||||
#include "metamod.h" // gpGlobals
|
|
||||||
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
MPlayer::MPlayer()
|
|
||||||
: isQueried(mFALSE),
|
|
||||||
cvarName(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Destructor
|
|
||||||
MPlayer::~MPlayer()
|
|
||||||
{
|
|
||||||
if(cvarName) {
|
|
||||||
free(cvarName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Copy constructor
|
|
||||||
MPlayer::MPlayer(const MPlayer& rhs)
|
|
||||||
: isQueried(rhs.isQueried),
|
|
||||||
cvarName(NULL)
|
|
||||||
{
|
|
||||||
if(rhs.cvarName) {
|
|
||||||
cvarName = strdup(rhs.cvarName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Assignment operator
|
|
||||||
MPlayer& DLLINTERNAL MPlayer::operator=(const MPlayer& rhs)
|
|
||||||
{
|
|
||||||
isQueried = rhs.isQueried;
|
|
||||||
|
|
||||||
if(cvarName) {
|
|
||||||
free(cvarName);
|
|
||||||
}
|
|
||||||
|
|
||||||
cvarName = NULL;
|
|
||||||
|
|
||||||
if(rhs.cvarName) {
|
|
||||||
cvarName = strdup(rhs.cvarName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Mark a player as querying a client cvar and stores the cvar name
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_ARGUMENT cvar is NULL
|
|
||||||
void DLLINTERNAL MPlayer::set_cvar_query(const char *cvar)
|
|
||||||
{
|
|
||||||
// Do not allow NULL as queried cvar since we use this as
|
|
||||||
// return value in is_querying_cvar as indication if a
|
|
||||||
// client cvar is queried.
|
|
||||||
if(!cvar) {
|
|
||||||
meta_errno = ME_ARGUMENT;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
isQueried = mTRUE;
|
|
||||||
if(cvarName) {
|
|
||||||
free(cvarName);
|
|
||||||
}
|
|
||||||
|
|
||||||
cvarName = strdup(cvar);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Unmark player as querying a client cvar
|
|
||||||
void DLLINTERNAL MPlayer::clear_cvar_query(const char* /*cvar*/)
|
|
||||||
{
|
|
||||||
isQueried = mFALSE;
|
|
||||||
if(cvarName) {
|
|
||||||
free(cvarName);
|
|
||||||
cvarName = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Check if a client cvar is queried for this player
|
|
||||||
// Returns NULL if not
|
|
||||||
// or the name of the cvar.
|
|
||||||
const char * DLLINTERNAL MPlayer::is_querying_cvar(void)
|
|
||||||
{
|
|
||||||
if(isQueried) {
|
|
||||||
return(cvarName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Mark a player as querying a client cvar and stores the cvar name
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_ARGUMENT cvar is NULL
|
|
||||||
void DLLINTERNAL MPlayerList::set_player_cvar_query(const edict_t *pEntity, const char *cvar)
|
|
||||||
{
|
|
||||||
int indx = ENTINDEX(const_cast<edict_t*>(pEntity));
|
|
||||||
|
|
||||||
if(indx < 1 || indx >= MPlayerList::NUM_SLOTS)
|
|
||||||
return; //maybe output a message?
|
|
||||||
|
|
||||||
players[indx].set_cvar_query(cvar);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Unmark player as querying a client cvar
|
|
||||||
void DLLINTERNAL MPlayerList::clear_player_cvar_query(const edict_t *pEntity, const char *cvar)
|
|
||||||
{
|
|
||||||
int indx = ENTINDEX(const_cast<edict_t*>(pEntity));
|
|
||||||
|
|
||||||
if(indx < 1 || indx >= MPlayerList::NUM_SLOTS)
|
|
||||||
return; //maybe output a message?
|
|
||||||
|
|
||||||
players[indx].clear_cvar_query(cvar);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DLLINTERNAL MPlayerList::clear_all_cvar_queries(void)
|
|
||||||
{
|
|
||||||
for(int indx=1; indx < MPlayerList::NUM_SLOTS; ++indx) {
|
|
||||||
players[indx].clear_cvar_query();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Check if a client cvar is queried for this player
|
|
||||||
// Returns NULL if not
|
|
||||||
// or the name of the cvar.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_NOTFOUND invalid entity
|
|
||||||
const char* DLLINTERNAL MPlayerList::is_querying_cvar(const edict_t *pEntity)
|
|
||||||
{
|
|
||||||
int indx = ENTINDEX(const_cast<edict_t*>(pEntity));
|
|
||||||
|
|
||||||
if(indx < 1 || indx > gpGlobals->maxClients) {
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(players[indx].is_querying_cvar());
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,532 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// mreg.cpp - functions for registered items (classes MRegCmd, MRegCmdList)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef linux
|
|
||||||
// enable extra routines in system header files, like strsignal
|
|
||||||
# ifndef _GNU_SOURCE
|
|
||||||
# define _GNU_SOURCE
|
|
||||||
# endif
|
|
||||||
#endif /* linux */
|
|
||||||
|
|
||||||
#include <string.h> // strsignal, strdup, etc
|
|
||||||
#include <errno.h> // strerror, etc
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "mreg.h" // me
|
|
||||||
#include "metamod.h" // Plugins, etc
|
|
||||||
#include "mlist.h" // class MPluginList
|
|
||||||
#include "mplugin.h" // class MPlugin
|
|
||||||
#include "types_meta.h" // mBOOL
|
|
||||||
#include "log_meta.h" // META_LOG, etc
|
|
||||||
#include "osdep.h" // os_safe_call, etc
|
|
||||||
|
|
||||||
|
|
||||||
///// class MRegCmd:
|
|
||||||
|
|
||||||
// Init values. It would probably be more "proper" to use containers and
|
|
||||||
// constructors, rather than arrays and init-functions.
|
|
||||||
void DLLINTERNAL MRegCmd::init(int idx)
|
|
||||||
{
|
|
||||||
index = idx;
|
|
||||||
name = NULL;
|
|
||||||
pfnCmd = NULL;
|
|
||||||
plugid = 0;
|
|
||||||
status = RG_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to call the function. Relies on OS-specific routine to attempt
|
|
||||||
// calling the function without generating a segfault from an unloaded
|
|
||||||
// plugin DLL.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_BADREQ function disabled/invalid
|
|
||||||
// - ME_ARGUMENT function pointer is null
|
|
||||||
mBOOL DLLINTERNAL MRegCmd::call(void) {
|
|
||||||
mBOOL ret;
|
|
||||||
|
|
||||||
// can we expect to call this function?
|
|
||||||
if(status != RG_VALID)
|
|
||||||
RETURN_ERRNO(mFALSE, ME_BADREQ);
|
|
||||||
if(!pfnCmd)
|
|
||||||
RETURN_ERRNO(mFALSE, ME_ARGUMENT);
|
|
||||||
|
|
||||||
// try to call this function
|
|
||||||
ret=os_safe_call(pfnCmd);
|
|
||||||
if(!ret) {
|
|
||||||
META_DEBUG(4, ("Plugin reg_cmd '%s' called after unloaded; removed from list", name));
|
|
||||||
status=RG_INVALID;
|
|
||||||
pfnCmd=NULL;
|
|
||||||
// NOTE: we can't free the malloc'd space for the name, as that
|
|
||||||
// would just re-introduce the segfault problem..
|
|
||||||
}
|
|
||||||
// meta_errno (if failed) is set already in os_safe_call()
|
|
||||||
return(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///// class MRegCmdList:
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
MRegCmdList::MRegCmdList(void)
|
|
||||||
: mlist(0), size(REG_CMD_GROWSIZE), endlist(0)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
mlist = (MRegCmd *) calloc(1, size * sizeof(MRegCmd));
|
|
||||||
// initialize array
|
|
||||||
for(i=0; i < size; i++)
|
|
||||||
mlist[i].init(i+1); // 1-based index
|
|
||||||
endlist=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to find a registered function with the given name.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_NOTFOUND couldn't find a matching function
|
|
||||||
MRegCmd * DLLINTERNAL MRegCmdList::find(const char *findname) {
|
|
||||||
int i;
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
if(!strcasecmp(mlist[i].name, findname))
|
|
||||||
return(&mlist[i]);
|
|
||||||
}
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the given name to the list and return the instance. This only
|
|
||||||
// writes the "name" to the new cmd; other fields are writtin by caller
|
|
||||||
// (meta_AddServerCommand).
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_NOMEM couldn't realloc or malloc for various parts
|
|
||||||
MRegCmd * DLLINTERNAL MRegCmdList::add(const char *addname) {
|
|
||||||
MRegCmd *icmd;
|
|
||||||
|
|
||||||
if(endlist==size) {
|
|
||||||
// grow array
|
|
||||||
MRegCmd *temp;
|
|
||||||
int i, newsize;
|
|
||||||
newsize=size+REG_CMD_GROWSIZE;
|
|
||||||
META_DEBUG(6, ("Growing reg cmd list from %d to %d", size, newsize));
|
|
||||||
temp = (MRegCmd *) realloc(mlist, newsize*sizeof(MRegCmd));
|
|
||||||
if(!temp) {
|
|
||||||
META_WARNING("Couldn't grow registered command list to %d for '%s': %s", newsize, addname, strerror(errno));
|
|
||||||
RETURN_ERRNO(NULL, ME_NOMEM);
|
|
||||||
}
|
|
||||||
mlist=temp;
|
|
||||||
size=newsize;
|
|
||||||
// initialize new (unused) entries
|
|
||||||
for(i=endlist; i<size; i++) {
|
|
||||||
memset(&mlist[i], 0, sizeof(mlist[i]));
|
|
||||||
mlist[i].init(i+1); // 1-based
|
|
||||||
}
|
|
||||||
}
|
|
||||||
icmd = &mlist[endlist];
|
|
||||||
|
|
||||||
// Malloc space separately for the command name, because:
|
|
||||||
// - Can't point to memory loc in plugin (another segv waiting to
|
|
||||||
// happen).
|
|
||||||
// - Can't point to memory in mlist which might get moved later by
|
|
||||||
// realloc (again, segv).
|
|
||||||
icmd->name=strdup(addname);
|
|
||||||
if(!icmd->name) {
|
|
||||||
META_WARNING("Couldn't strdup for adding reg cmd name '%s': %s",
|
|
||||||
addname, strerror(errno));
|
|
||||||
RETURN_ERRNO(NULL, ME_NOMEM);
|
|
||||||
}
|
|
||||||
endlist++;
|
|
||||||
|
|
||||||
return(icmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable any functions belonging to the given plugin (by index id).
|
|
||||||
void DLLINTERNAL MRegCmdList::disable(int plugin_id) {
|
|
||||||
int i;
|
|
||||||
for(i=0; i < size; i++) {
|
|
||||||
if(mlist[i].plugid == plugin_id)
|
|
||||||
mlist[i].status = RG_INVALID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// List all the registered commands.
|
|
||||||
void DLLINTERNAL MRegCmdList::show(void) {
|
|
||||||
int i, n=0, a=0;
|
|
||||||
MRegCmd *icmd;
|
|
||||||
MPlugin *iplug;
|
|
||||||
char bplug[18+1]; // +1 for term null
|
|
||||||
|
|
||||||
META_CONS("Registered plugin commands:");
|
|
||||||
META_CONS(" %*s %-*s %-s",
|
|
||||||
WIDTH_MAX_REG, "",
|
|
||||||
sizeof(bplug)-1, "plugin", "command");
|
|
||||||
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
icmd = &mlist[i];
|
|
||||||
|
|
||||||
if(icmd->status==RG_VALID) {
|
|
||||||
iplug=Plugins->find(icmd->plugid);
|
|
||||||
|
|
||||||
if(iplug)
|
|
||||||
STRNCPY(bplug, iplug->desc, sizeof(bplug));
|
|
||||||
else
|
|
||||||
STRNCPY(bplug, "(unknown)", sizeof(bplug));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
STRNCPY(bplug, "(unloaded)", sizeof(bplug));
|
|
||||||
|
|
||||||
META_CONS(" [%*d] %-*s %-s",
|
|
||||||
WIDTH_MAX_REG, icmd->index,
|
|
||||||
sizeof(bplug)-1, bplug,
|
|
||||||
icmd->name);
|
|
||||||
|
|
||||||
if(icmd->status==RG_VALID)
|
|
||||||
a++;
|
|
||||||
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
META_CONS("%d commands, %d available (%d allocated)", n, a, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// List all the registered commands for the given plugin id.
|
|
||||||
void DLLINTERNAL MRegCmdList::show(int plugin_id) {
|
|
||||||
int i, n=0;
|
|
||||||
MRegCmd *icmd;
|
|
||||||
|
|
||||||
/*
|
|
||||||
// If OS doesn't support DLFNAME, then we can't know what the plugin's
|
|
||||||
// registered cvars are.
|
|
||||||
DLFNAME(NULL);
|
|
||||||
if(meta_errno==ME_OSNOTSUP) {
|
|
||||||
META_CONS("Registered commands: unknown (can't get info under this OS)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
META_CONS("Registered commands:");
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
icmd = &mlist[i];
|
|
||||||
if(icmd->plugid != plugin_id)
|
|
||||||
continue;
|
|
||||||
META_CONS(" %s", icmd->name);
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
META_CONS("%d commands", n);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///// class MRegCvar:
|
|
||||||
|
|
||||||
// Init values. It would probably be more "proper" to use containers and
|
|
||||||
// constructors, rather than arrays and init-functions.
|
|
||||||
void DLLINTERNAL MRegCvar::init(int idx)
|
|
||||||
{
|
|
||||||
index = idx;
|
|
||||||
data = NULL;
|
|
||||||
plugid = 0;
|
|
||||||
status = RG_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the cvar, copying values from given cvar.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_ARGUMENT given cvar doesn't match this cvar
|
|
||||||
mBOOL DLLINTERNAL MRegCvar::set(cvar_t *src) {
|
|
||||||
if(strcasecmp(src->name, data->name)) {
|
|
||||||
META_WARNING("Tried to set cvar with mismatched name; src=%s dst=%s",
|
|
||||||
src->name, data->name);
|
|
||||||
RETURN_ERRNO(mFALSE, ME_ARGUMENT);
|
|
||||||
}
|
|
||||||
// Would like to free() existing string, but can't tell where it was
|
|
||||||
// allocated...
|
|
||||||
data->string = strdup(src->string);
|
|
||||||
data->flags = src->flags;
|
|
||||||
data->value = src->value;
|
|
||||||
data->next = src->next;
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///// class MRegCvarList:
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
MRegCvarList::MRegCvarList(void)
|
|
||||||
: vlist(0), size(REG_CVAR_GROWSIZE), endlist(0)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
vlist = (MRegCvar *) calloc(1, size * sizeof(MRegCvar));
|
|
||||||
// initialize array
|
|
||||||
for(i=0; i < size; i++)
|
|
||||||
vlist[i].init(i+1); // 1-based
|
|
||||||
endlist=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the given cvar name to the list and return the instance. This only
|
|
||||||
// writes the "name" to the new cvar; other fields are written with
|
|
||||||
// cvar::set().
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_NOMEM couldn't alloc or realloc for various parts
|
|
||||||
MRegCvar * DLLINTERNAL MRegCvarList::add(const char *addname) {
|
|
||||||
MRegCvar *icvar;
|
|
||||||
|
|
||||||
if(endlist==size) {
|
|
||||||
// grow array
|
|
||||||
MRegCvar *temp;
|
|
||||||
int i, newsize;
|
|
||||||
newsize=size+REG_CVAR_GROWSIZE;
|
|
||||||
META_DEBUG(6, ("Growing reg cvar list from %d to %d", size, newsize));
|
|
||||||
temp = (MRegCvar *) realloc(vlist, newsize*sizeof(MRegCvar));
|
|
||||||
if(!temp) {
|
|
||||||
META_WARNING("Couldn't grow registered cvar list to %d for '%s'; %s", newsize, addname, strerror(errno));
|
|
||||||
RETURN_ERRNO(NULL, ME_NOMEM);
|
|
||||||
}
|
|
||||||
vlist=temp;
|
|
||||||
size=newsize;
|
|
||||||
// initialize new (unused) entries
|
|
||||||
for(i=endlist; i<size; i++) {
|
|
||||||
memset(&vlist[i], 0, sizeof(vlist[i]));
|
|
||||||
vlist[i].init(i+1); // 1-based
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
icvar = &vlist[endlist];
|
|
||||||
|
|
||||||
// Malloc space for the cvar and cvar name, for two reasons:
|
|
||||||
// - Can't point to memory loc in plugin (another segv waiting to
|
|
||||||
// happen).
|
|
||||||
// - Can't point to memory in vlist which might get moved later by
|
|
||||||
// realloc (again, segv).
|
|
||||||
icvar->data = (cvar_t *) calloc(1, sizeof(cvar_t));
|
|
||||||
if(!icvar->data) {
|
|
||||||
META_WARNING("Couldn't malloc cvar for adding reg cvar name '%s': %s",
|
|
||||||
addname, strerror(errno));
|
|
||||||
RETURN_ERRNO(NULL, ME_NOMEM);
|
|
||||||
}
|
|
||||||
icvar->data->name=strdup(addname);
|
|
||||||
if(!icvar->data->name) {
|
|
||||||
META_WARNING("Couldn't strdup for adding reg cvar name '%s': %s",
|
|
||||||
addname, strerror(errno));
|
|
||||||
RETURN_ERRNO(NULL, ME_NOMEM);
|
|
||||||
}
|
|
||||||
endlist++;
|
|
||||||
|
|
||||||
return(icvar);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to find a registered cvar with the given name.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_NOTFOUND couldn't find a matching cvar
|
|
||||||
MRegCvar * DLLINTERNAL MRegCvarList::find(const char *findname) {
|
|
||||||
int i;
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
if(!strcasecmp(vlist[i].data->name, findname))
|
|
||||||
return(&vlist[i]);
|
|
||||||
}
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable any cvars belonging to the given plugin (by index id).
|
|
||||||
void DLLINTERNAL MRegCvarList::disable(int plugin_id) {
|
|
||||||
int i;
|
|
||||||
MRegCvar *icvar;
|
|
||||||
for(i=0; i < size; i++) {
|
|
||||||
icvar=&vlist[i];
|
|
||||||
if(icvar->plugid == plugin_id) {
|
|
||||||
icvar->status = RG_INVALID;
|
|
||||||
icvar->plugid = 0;
|
|
||||||
// Decided not to do this, in order to keep pre-existing values
|
|
||||||
// after a plugin reload.
|
|
||||||
// CVAR_SET_STRING(icvar->data->name, "[metamod: cvar invalid; plugin unloaded]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// List all the registered cvars.
|
|
||||||
void DLLINTERNAL MRegCvarList::show(void) {
|
|
||||||
int i, n=0, a=0;
|
|
||||||
MRegCvar *icvar;
|
|
||||||
MPlugin *iplug;
|
|
||||||
char bplug[13+1], bname[20+1], bval[15+1]; // +1 for term null
|
|
||||||
|
|
||||||
META_CONS("Registered plugin cvars:");
|
|
||||||
META_CONS(" %*s %-*s %-*s %*s %s",
|
|
||||||
WIDTH_MAX_REG, "",
|
|
||||||
sizeof(bplug)-1, "plugin",
|
|
||||||
sizeof(bname)-1, "cvar",
|
|
||||||
sizeof(bval)-1, "float value",
|
|
||||||
"string value");
|
|
||||||
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
icvar = &vlist[i];
|
|
||||||
if(icvar->status==RG_VALID) {
|
|
||||||
iplug=Plugins->find(icvar->plugid);
|
|
||||||
if(iplug)
|
|
||||||
STRNCPY(bplug, iplug->desc, sizeof(bplug));
|
|
||||||
else
|
|
||||||
STRNCPY(bplug, "(unknown)", sizeof(bplug));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
STRNCPY(bplug, "(unloaded)", sizeof(bplug));
|
|
||||||
STRNCPY(bname, icvar->data->name, sizeof(bname));
|
|
||||||
safevoid_snprintf(bval, sizeof(bval), "%f", icvar->data->value);
|
|
||||||
META_CONS(" [%*d] %-*s %-*s %*s %s",
|
|
||||||
WIDTH_MAX_REG, icvar->index,
|
|
||||||
sizeof(bplug)-1, bplug,
|
|
||||||
sizeof(bname)-1, bname,
|
|
||||||
sizeof(bval)-1, bval,
|
|
||||||
icvar->data->string);
|
|
||||||
if(icvar->status==RG_VALID)
|
|
||||||
a++;
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
META_CONS("%d cvars, %d available (%d allocated)", n, a, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// List the registered cvars for the given plugin id.
|
|
||||||
void DLLINTERNAL MRegCvarList::show(int plugin_id) {
|
|
||||||
int i, n=0;
|
|
||||||
MRegCvar *icvar;
|
|
||||||
char bname[30+1], bval[15+1]; // +1 for term null
|
|
||||||
|
|
||||||
/*
|
|
||||||
// If OS doesn't support DLFNAME, then we can't know what the plugin's
|
|
||||||
// registered cvars are.
|
|
||||||
DLFNAME(NULL);
|
|
||||||
if(meta_errno==ME_OSNOTSUP) {
|
|
||||||
META_CONS("Registered cvars: unknown (can't get info under this OS)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
META_CONS("%-*s %*s %s",
|
|
||||||
sizeof(bname)-1, "Registered cvars:",
|
|
||||||
sizeof(bval)-1, "float value",
|
|
||||||
"string value");
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
icvar = &vlist[i];
|
|
||||||
if(icvar->plugid != plugin_id)
|
|
||||||
continue;
|
|
||||||
STRNCPY(bname, icvar->data->name, sizeof(bname));
|
|
||||||
safevoid_snprintf(bval, sizeof(bval), "%f", icvar->data->value);
|
|
||||||
META_CONS(" %-*s %*s %s",
|
|
||||||
sizeof(bname)-1, bname,
|
|
||||||
sizeof(bval)-1, bval,
|
|
||||||
icvar->data->string);
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
META_CONS("%d cvars", n);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///// class MRegMsgList:
|
|
||||||
|
|
||||||
// Constructor
|
|
||||||
MRegMsgList::MRegMsgList(void)
|
|
||||||
: size(MAX_REG_MSGS), endlist(0)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
// initialize array
|
|
||||||
memset(mlist, 0, sizeof(mlist));
|
|
||||||
for(i=0; i < size; i++) {
|
|
||||||
mlist[i].index=i+1; // 1-based
|
|
||||||
}
|
|
||||||
endlist=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the given user msg the list and return the instance.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_MAXREACHED reached max number of msgs allowed
|
|
||||||
MRegMsg * DLLINTERNAL MRegMsgList::add(const char *addname, int addmsgid, int addsize) {
|
|
||||||
MRegMsg *imsg;
|
|
||||||
|
|
||||||
if(endlist==size) {
|
|
||||||
// all slots used
|
|
||||||
META_ERROR("Couldn't add registered msg '%s' to list; reached max msgs (%d)",
|
|
||||||
addname, size);
|
|
||||||
RETURN_ERRNO(NULL, ME_MAXREACHED);
|
|
||||||
}
|
|
||||||
|
|
||||||
imsg = &mlist[endlist];
|
|
||||||
endlist++;
|
|
||||||
|
|
||||||
// Copy msg data into empty slot.
|
|
||||||
// Note: 'addname' assumed to be a constant string allocated in the
|
|
||||||
// gamedll.
|
|
||||||
imsg->name=addname;
|
|
||||||
imsg->msgid=addmsgid;
|
|
||||||
imsg->size=addsize;
|
|
||||||
|
|
||||||
return(imsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to find a registered msg with the given name.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_NOTFOUND couldn't find a matching cvar
|
|
||||||
MRegMsg * DLLINTERNAL MRegMsgList::find(const char *findname) {
|
|
||||||
int i;
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
if(!mm_strcmp(mlist[i].name, findname))
|
|
||||||
return(&mlist[i]);
|
|
||||||
}
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to find a registered msg with the given msgid.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_NOTFOUND couldn't find a matching cvar
|
|
||||||
MRegMsg * DLLINTERNAL MRegMsgList::find(int findmsgid) {
|
|
||||||
int i;
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
if(mlist[i].msgid == findmsgid)
|
|
||||||
return(&mlist[i]);
|
|
||||||
}
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
// List the registered usermsgs for the gamedll.
|
|
||||||
void DLLINTERNAL MRegMsgList::show(void) {
|
|
||||||
int i, n=0;
|
|
||||||
MRegMsg *imsg;
|
|
||||||
char bname[25+1]; // +1 for term null
|
|
||||||
|
|
||||||
META_CONS("%-*s %5s %5s",
|
|
||||||
sizeof(bname)-1, "Game registered user msgs:", "msgid", "size");
|
|
||||||
for(i=0; i < endlist; i++) {
|
|
||||||
imsg = &mlist[i];
|
|
||||||
STRNCPY(bname, imsg->name, sizeof(bname));
|
|
||||||
META_CONS(" %-*s %3d %3d",
|
|
||||||
sizeof(bname)-1, bname,
|
|
||||||
imsg->msgid,
|
|
||||||
imsg->size);
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
META_CONS("%d game user msgs", n);
|
|
||||||
}
|
|
||||||
@@ -1,395 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// mutil.cpp - utility functions to provide to plugins
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h> // vsnprintf(), etc
|
|
||||||
#include <stdarg.h> // vs_start(), etc
|
|
||||||
#include <stdlib.h> // strtol()
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "meta_api.h" //
|
|
||||||
#include "mutil.h" // me
|
|
||||||
#include "mhook.h" // class MHookList, etc
|
|
||||||
#include "linkent.h" // ENTITY_FN, etc
|
|
||||||
#include "metamod.h" // Hooks, etc
|
|
||||||
#include "types_meta.h" // mBOOL
|
|
||||||
#include "osdep.h" // win32 vsnprintf, etc
|
|
||||||
#include "sdk_util.h" // ALERT, etc
|
|
||||||
|
|
||||||
static hudtextparms_t default_csay_tparms = {
|
|
||||||
-1, 0.25, // x, y
|
|
||||||
2, // effect
|
|
||||||
0, 255, 0, 0, // r, g, b, a1
|
|
||||||
0, 0, 0, 0, // r2, g2, b2, a2
|
|
||||||
0, 0, 10, 10, // fadein, fadeout, hold, fxtime
|
|
||||||
1 // channel
|
|
||||||
};
|
|
||||||
|
|
||||||
// Log to console; newline added.
|
|
||||||
static void mutil_LogConsole(plid_t /* plid */, const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
char buf[MAX_LOGMSG_LEN];
|
|
||||||
unsigned int len;
|
|
||||||
|
|
||||||
va_start(ap, fmt);
|
|
||||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
// end msg with newline
|
|
||||||
len=strlen(buf);
|
|
||||||
if(len < sizeof(buf)-2) // -1 null, -1 for newline
|
|
||||||
strcat(buf, "\n");
|
|
||||||
else
|
|
||||||
buf[len-1] = '\n';
|
|
||||||
|
|
||||||
SERVER_PRINT(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log regular message to logs; newline added.
|
|
||||||
static void mutil_LogMessage(plid_t plid, const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
char buf[MAX_LOGMSG_LEN];
|
|
||||||
plugin_info_t *plinfo;
|
|
||||||
|
|
||||||
plinfo=(plugin_info_t *)plid;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
ALERT(at_logged, "[%s] %s\n", plinfo->logtag, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log an error message to logs; newline added.
|
|
||||||
static void mutil_LogError(plid_t plid, const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
char buf[MAX_LOGMSG_LEN];
|
|
||||||
plugin_info_t *plinfo;
|
|
||||||
|
|
||||||
plinfo=(plugin_info_t *)plid;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
ALERT(at_logged, "[%s] ERROR: %s\n", plinfo->logtag, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log a message only if cvar "developer" set; newline added.
|
|
||||||
static void mutil_LogDeveloper(plid_t plid, const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
char buf[MAX_LOGMSG_LEN];
|
|
||||||
plugin_info_t *plinfo;
|
|
||||||
|
|
||||||
if((int)CVAR_GET_FLOAT("developer") == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
plinfo=(plugin_info_t *)plid;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
ALERT(at_logged, "[%s] dev: %s\n", plinfo->logtag, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print a center-message, with text parameters and varargs. Provides
|
|
||||||
// functionality to the above center_say interfaces.
|
|
||||||
static void mutil_CenterSayVarargs(plid_t plid, hudtextparms_t tparms,
|
|
||||||
const char *fmt, va_list ap)
|
|
||||||
{
|
|
||||||
char buf[MAX_LOGMSG_LEN];
|
|
||||||
int n;
|
|
||||||
edict_t *pEntity;
|
|
||||||
|
|
||||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
||||||
|
|
||||||
mutil_LogMessage(plid, "(centersay) %s", buf);
|
|
||||||
for(n=1; n <= gpGlobals->maxClients; n++) {
|
|
||||||
pEntity=INDEXENT(n);
|
|
||||||
META_UTIL_HudMessage(pEntity, tparms, buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print message on center of all player's screens. Uses default text
|
|
||||||
// parameters (color green, 10 second fade-in).
|
|
||||||
static void mutil_CenterSay(plid_t plid, const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
mutil_CenterSayVarargs(plid, default_csay_tparms, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print a center-message, with given text parameters.
|
|
||||||
static void mutil_CenterSayParms(plid_t plid, hudtextparms_t tparms, const char *fmt, ...) {
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
mutil_CenterSayVarargs(plid, tparms, fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow plugins to call the entity functions in the GameDLL. In
|
|
||||||
// particular, calling "player()" as needed by most Bots. Suggested by
|
|
||||||
// Jussi Kivilinna.
|
|
||||||
static qboolean mutil_CallGameEntity(plid_t plid, const char *entStr, entvars_t *pev) {
|
|
||||||
plugin_info_t *plinfo;
|
|
||||||
ENTITY_FN pfnEntity;
|
|
||||||
|
|
||||||
plinfo=(plugin_info_t *)plid;
|
|
||||||
META_DEBUG(8, ("Looking up game entity '%s' for plugin '%s'", entStr,
|
|
||||||
plinfo->name));
|
|
||||||
pfnEntity = (ENTITY_FN) DLSYM(GameDLL.handle, entStr);
|
|
||||||
if(!pfnEntity) {
|
|
||||||
META_WARNING("Couldn't find game entity '%s' in game DLL '%s' for plugin '%s'", entStr, GameDLL.name, plinfo->name);
|
|
||||||
return(false);
|
|
||||||
}
|
|
||||||
META_DEBUG(7, ("Calling game entity '%s' for plugin '%s'", entStr,
|
|
||||||
plinfo->name));
|
|
||||||
(*pfnEntity)(pev);
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find a usermsg, registered by the gamedll, with the corresponding
|
|
||||||
// msgname, and return remaining info about it (msgid, size).
|
|
||||||
static int mutil_GetUserMsgID(plid_t plid, const char *msgname, int *size) {
|
|
||||||
plugin_info_t *plinfo;
|
|
||||||
MRegMsg *umsg;
|
|
||||||
|
|
||||||
plinfo=(plugin_info_t *)plid;
|
|
||||||
META_DEBUG(8, ("Looking up usermsg name '%s' for plugin '%s'", msgname,
|
|
||||||
plinfo->name));
|
|
||||||
umsg=RegMsgs->find(msgname);
|
|
||||||
if(umsg) {
|
|
||||||
if(size)
|
|
||||||
*size=umsg->size;
|
|
||||||
return(umsg->msgid);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find a usermsg, registered by the gamedll, with the corresponding
|
|
||||||
// msgid, and return remaining info about it (msgname, size).
|
|
||||||
static const char *mutil_GetUserMsgName(plid_t plid, int msgid, int *size) {
|
|
||||||
plugin_info_t *plinfo;
|
|
||||||
MRegMsg *umsg;
|
|
||||||
|
|
||||||
plinfo=(plugin_info_t *)plid;
|
|
||||||
META_DEBUG(8, ("Looking up usermsg id '%d' for plugin '%s'", msgid,
|
|
||||||
plinfo->name));
|
|
||||||
// Guess names for any built-in Engine messages mentioned in the SDK;
|
|
||||||
// from dlls/util.h.
|
|
||||||
if(msgid < 64) {
|
|
||||||
switch(msgid) {
|
|
||||||
case SVC_TEMPENTITY:
|
|
||||||
if(size) *size=-1;
|
|
||||||
return("tempentity?");
|
|
||||||
case SVC_INTERMISSION:
|
|
||||||
if(size) *size=-1;
|
|
||||||
return("intermission?");
|
|
||||||
case SVC_CDTRACK:
|
|
||||||
if(size) *size=-1;
|
|
||||||
return("cdtrack?");
|
|
||||||
case SVC_WEAPONANIM:
|
|
||||||
if(size) *size=-1;
|
|
||||||
return("weaponanim?");
|
|
||||||
case SVC_ROOMTYPE:
|
|
||||||
if(size) *size=-1;
|
|
||||||
return("roomtype?");
|
|
||||||
case SVC_DIRECTOR:
|
|
||||||
if(size) *size=-1;
|
|
||||||
return("director?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
umsg=RegMsgs->find(msgid);
|
|
||||||
if(umsg) {
|
|
||||||
if(size)
|
|
||||||
*size=umsg->size;
|
|
||||||
// 'name' is assumed to be a constant string, allocated in the
|
|
||||||
// gamedll.
|
|
||||||
return(umsg->name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the full path of the plugin's loaded dll/so file.
|
|
||||||
static const char *mutil_GetPluginPath(plid_t plid) {
|
|
||||||
static char buf[PATH_MAX];
|
|
||||||
MPlugin *plug;
|
|
||||||
|
|
||||||
plug=Plugins->find(plid);
|
|
||||||
if(!plug) {
|
|
||||||
META_WARNING("GetPluginPath: couldn't find plugin '%s'",
|
|
||||||
plid->name);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
STRNCPY(buf, plug->pathname, sizeof(buf));
|
|
||||||
return(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return various string-based info about the game/MOD/gamedll.
|
|
||||||
static const char *mutil_GetGameInfo(plid_t plid, ginfo_t type) {
|
|
||||||
static char buf[MAX_STRBUF_LEN];
|
|
||||||
const char *cp;
|
|
||||||
switch(type) {
|
|
||||||
case GINFO_NAME:
|
|
||||||
cp=GameDLL.name;
|
|
||||||
break;
|
|
||||||
case GINFO_DESC:
|
|
||||||
cp=GameDLL.desc;
|
|
||||||
break;
|
|
||||||
case GINFO_GAMEDIR:
|
|
||||||
cp=GameDLL.gamedir;
|
|
||||||
break;
|
|
||||||
case GINFO_DLL_FULLPATH:
|
|
||||||
cp=GameDLL.pathname;
|
|
||||||
break;
|
|
||||||
case GINFO_DLL_FILENAME:
|
|
||||||
cp=GameDLL.file;
|
|
||||||
break;
|
|
||||||
case GINFO_REALDLL_FULLPATH:
|
|
||||||
cp=GameDLL.real_pathname;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
META_WARNING("GetGameInfo: invalid request '%d' from plugin '%s'",
|
|
||||||
type, plid->name);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
STRNCPY(buf, cp, sizeof(buf));
|
|
||||||
return(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mutil_LoadMetaPlugin(plid_t plid, const char *fname, PLUG_LOADTIME now, void **plugin_handle)
|
|
||||||
{
|
|
||||||
MPlugin *pl_loaded;
|
|
||||||
|
|
||||||
if(NULL == fname) {
|
|
||||||
return(ME_ARGUMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
meta_errno = ME_NOERROR;
|
|
||||||
if(!(pl_loaded=Plugins->plugin_addload(plid, fname, now))) {
|
|
||||||
if(plugin_handle)
|
|
||||||
*plugin_handle = NULL;
|
|
||||||
return(meta_errno);
|
|
||||||
} else {
|
|
||||||
if(plugin_handle)
|
|
||||||
*plugin_handle = (void*)pl_loaded->handle;
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mutil_UnloadMetaPlugin(plid_t plid, const char *fname, PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
|
|
||||||
{
|
|
||||||
MPlugin *findp = NULL;
|
|
||||||
int pindex;
|
|
||||||
char* endptr;
|
|
||||||
|
|
||||||
if(NULL == fname) {
|
|
||||||
return(ME_ARGUMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
pindex = strtol(fname, &endptr, 10);
|
|
||||||
if(*fname != '\0' && *endptr == '\0')
|
|
||||||
findp = Plugins->find(pindex);
|
|
||||||
else
|
|
||||||
findp = Plugins->find_match(fname);
|
|
||||||
|
|
||||||
if(!findp)
|
|
||||||
return(meta_errno);
|
|
||||||
|
|
||||||
meta_errno = ME_NOERROR;
|
|
||||||
|
|
||||||
if(findp->plugin_unload(plid, now, reason))
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
return(meta_errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mutil_UnloadMetaPluginByHandle(plid_t plid, void *plugin_handle, PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
|
|
||||||
{
|
|
||||||
MPlugin *findp;
|
|
||||||
|
|
||||||
if(NULL == plugin_handle) {
|
|
||||||
return(ME_ARGUMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(findp=Plugins->find((DLHANDLE)plugin_handle)))
|
|
||||||
return(ME_NOTFOUND);
|
|
||||||
|
|
||||||
meta_errno = ME_NOERROR;
|
|
||||||
|
|
||||||
if(findp->plugin_unload(plid, now, reason))
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
return(meta_errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if player is being queried for cvar
|
|
||||||
static const char * mutil_IsQueryingClientCvar(plid_t /*plid*/, const edict_t *player) {
|
|
||||||
return(g_Players.is_querying_cvar(player));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
static int mutil_MakeRequestID(plid_t /*plid*/) {
|
|
||||||
return(abs(0xbeef<<16) + (++requestid_counter));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
static void mutil_GetHookTables(plid_t plid, enginefuncs_t **peng, DLL_FUNCTIONS **pdll, NEW_DLL_FUNCTIONS **pnewdll) {
|
|
||||||
if (peng)
|
|
||||||
*peng = &meta_engfuncs;
|
|
||||||
if (pdll)
|
|
||||||
*pdll = g_pHookedDllFunctions;
|
|
||||||
if (pnewdll)
|
|
||||||
*pnewdll = g_pHookedNewDllFunctions;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Meta Utility Function table.
|
|
||||||
mutil_funcs_t MetaUtilFunctions = {
|
|
||||||
mutil_LogConsole, // pfnLogConsole
|
|
||||||
mutil_LogMessage, // pfnLogMessage
|
|
||||||
mutil_LogError, // pfnLogError
|
|
||||||
mutil_LogDeveloper, // pfnLogDeveloper
|
|
||||||
mutil_CenterSay, // pfnCenterSay
|
|
||||||
mutil_CenterSayParms, // pfnCenterSayParms
|
|
||||||
mutil_CenterSayVarargs, // pfnCenterSayVarargs
|
|
||||||
mutil_CallGameEntity, // pfnCallGameEntity
|
|
||||||
mutil_GetUserMsgID, // pfnGetUserMsgID
|
|
||||||
mutil_GetUserMsgName, // pfnGetUserMsgName
|
|
||||||
mutil_GetPluginPath, // pfnGetPluginPath
|
|
||||||
mutil_GetGameInfo, // pfnGetGameInfo
|
|
||||||
mutil_LoadMetaPlugin, // pfnLoadPlugin
|
|
||||||
mutil_UnloadMetaPlugin, // pfnUnloadPlugin
|
|
||||||
mutil_UnloadMetaPluginByHandle, // pfnUnloadPluginByHandle
|
|
||||||
mutil_IsQueryingClientCvar, // pfnIsQueryingClientCvar
|
|
||||||
mutil_MakeRequestID, // pfnMakeRequestID
|
|
||||||
mutil_GetHookTables, // pfnGetHookTables
|
|
||||||
};
|
|
||||||
@@ -1,399 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// osdep.cpp - routines for operating system differences
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef linux
|
|
||||||
// enable extra routines in system header files, like dladdr
|
|
||||||
# ifndef _GNU_SOURCE
|
|
||||||
# define _GNU_SOURCE
|
|
||||||
# endif
|
|
||||||
#include <dlfcn.h> // dlopen, dladdr, etc
|
|
||||||
#endif /* linux */
|
|
||||||
|
|
||||||
#include <string.h> // strpbrk, etc
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "osdep.h" // me
|
|
||||||
#include "mreg.h" // RG_VALID, etc
|
|
||||||
#include "log_meta.h" // META_ERROR, etc
|
|
||||||
#include "types_meta.h" // mBOOL
|
|
||||||
#include "support_meta.h" // MAX_STRBUF_LEN
|
|
||||||
#include "limits.h" // INT_MAX
|
|
||||||
|
|
||||||
|
|
||||||
mBOOL dlclose_handle_invalid;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
// Since windows doesn't provide a verison of strtok_r(), we include one
|
|
||||||
// here. This may or may not operate exactly like strtok_r(), but does
|
|
||||||
// what we need it it do.
|
|
||||||
char * DLLINTERNAL my_strtok_r(char *s, const char *delim, char **ptrptr) {
|
|
||||||
char *begin=NULL;
|
|
||||||
char *end=NULL;
|
|
||||||
char *rest=NULL;
|
|
||||||
if(s)
|
|
||||||
begin=s;
|
|
||||||
else
|
|
||||||
begin=*ptrptr;
|
|
||||||
if(!begin)
|
|
||||||
return(NULL);
|
|
||||||
end=strpbrk(begin, delim);
|
|
||||||
if(end) {
|
|
||||||
*end='\0';
|
|
||||||
rest=end+1;
|
|
||||||
*ptrptr=rest+strspn(rest, delim);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
*ptrptr=NULL;
|
|
||||||
return(begin);
|
|
||||||
}
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef linux
|
|
||||||
char * DLLINTERNAL my_strlwr(char *s) {
|
|
||||||
char *c;
|
|
||||||
if(!s)
|
|
||||||
return(0);
|
|
||||||
for(c=s;*c;c++)
|
|
||||||
*c = tolower(*c);
|
|
||||||
return(s);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef DO_NOT_FIX_VARARG_ENGINE_API_WARPERS
|
|
||||||
// Microsoft's msvcrt.dll:vsnprintf is buggy and so is vsnprintf on some glibc versions.
|
|
||||||
// We use wrapper function to fix bugs.
|
|
||||||
// from: http://sourceforge.net/tracker/index.php?func=detail&aid=1083721&group_id=2435&atid=102435
|
|
||||||
int DLLINTERNAL safe_vsnprintf(char* s, size_t n, const char *format, va_list src_ap) {
|
|
||||||
va_list ap;
|
|
||||||
int res;
|
|
||||||
char *tmpbuf;
|
|
||||||
size_t bufsize = n;
|
|
||||||
|
|
||||||
if(s && n>0)
|
|
||||||
s[0]=0;
|
|
||||||
|
|
||||||
// If the format string is empty, nothing to do.
|
|
||||||
if(!format || !*format)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
// The supplied count may be big enough. Try to use the library
|
|
||||||
// vsnprintf, fixing up the case where the library function
|
|
||||||
// neglects to terminate with '/0'.
|
|
||||||
if(n > 0)
|
|
||||||
{
|
|
||||||
// A NULL destination will cause a segfault with vsnprintf.
|
|
||||||
// if n > 0. Nor do we want to copy our tmpbuf to NULL later.
|
|
||||||
if(!s)
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
va_copy(ap, src_ap);
|
|
||||||
res = vsnprintf(s, n, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
if(res > 0) {
|
|
||||||
if((unsigned)res == n)
|
|
||||||
s[res - 1] = 0;
|
|
||||||
return(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If n is already larger than INT_MAX, increasing it won't
|
|
||||||
// help.
|
|
||||||
if(n > INT_MAX)
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
// Try a larger buffer.
|
|
||||||
bufsize *= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bufsize < 1024)
|
|
||||||
bufsize = 1024;
|
|
||||||
|
|
||||||
tmpbuf = (char *)malloc(bufsize * sizeof(char));
|
|
||||||
if(!tmpbuf)
|
|
||||||
return(-1);
|
|
||||||
|
|
||||||
va_copy(ap, src_ap);
|
|
||||||
res = vsnprintf(tmpbuf, bufsize, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
// The test for bufsize limit is probably not necesary
|
|
||||||
// with 2GB address space limit, since, in practice, malloc will
|
|
||||||
// fail well before INT_MAX.
|
|
||||||
while(res < 0 && bufsize <= INT_MAX) {
|
|
||||||
char * newbuf;
|
|
||||||
|
|
||||||
bufsize *= 2;
|
|
||||||
newbuf = (char*)realloc(tmpbuf, bufsize * sizeof(char));
|
|
||||||
|
|
||||||
if(!newbuf)
|
|
||||||
break;
|
|
||||||
|
|
||||||
tmpbuf = newbuf;
|
|
||||||
|
|
||||||
va_copy(ap, src_ap);
|
|
||||||
res = vsnprintf(tmpbuf, bufsize, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(res > 0 && n > 0) {
|
|
||||||
if(n > (unsigned)res)
|
|
||||||
memcpy(s, tmpbuf, (res + 1) * sizeof (char));
|
|
||||||
else {
|
|
||||||
memcpy(s, tmpbuf, (n - 1) * sizeof (char));
|
|
||||||
s[n - 1] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(tmpbuf);
|
|
||||||
return(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
int DLLINTERNAL safe_snprintf(char* s, size_t n, const char* format, ...) {
|
|
||||||
int res;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, format);
|
|
||||||
res = safe_vsnprintf(s, n, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
return(res);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void DLLINTERNAL safevoid_vsnprintf(char* s, size_t n, const char *format, va_list ap) {
|
|
||||||
int res;
|
|
||||||
|
|
||||||
if(!s || n <= 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If the format string is empty, nothing to do.
|
|
||||||
if(!format || !*format) {
|
|
||||||
s[0]=0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = vsnprintf(s, n, format, ap);
|
|
||||||
|
|
||||||
// w32api returns -1 on too long write, glibc returns number of bytes it could have written if there were enough space
|
|
||||||
// w32api doesn't write null at all, some buggy glibc don't either
|
|
||||||
if(res < 0 || (size_t)res >= n)
|
|
||||||
s[n-1]=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DLLINTERNAL safevoid_snprintf(char* s, size_t n, const char* format, ...) {
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, format);
|
|
||||||
safevoid_vsnprintf(s, n, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
// Windows doesn't provide a functon analagous to dlerr() that returns a
|
|
||||||
// string describing the error, so we include one here, as exampled at:
|
|
||||||
// http://msdn.microsoft.com/library/en-us/debug/errors_0sdh.asp
|
|
||||||
// except without FORMAT_MESSAGE_ALLOCATE_BUFFER, since we use a local
|
|
||||||
// static buffer.
|
|
||||||
char * DLLINTERNAL str_GetLastError(void) {
|
|
||||||
static char buf[MAX_STRBUF_LEN];
|
|
||||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL, GetLastError(),
|
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //! Default language
|
|
||||||
(LPTSTR) &buf, MAX_STRBUF_LEN-1, NULL);
|
|
||||||
return(buf);
|
|
||||||
}
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
|
|
||||||
// Find the filename of the DLL/shared-lib where the given memory location
|
|
||||||
// exists.
|
|
||||||
#ifdef linux
|
|
||||||
// Errno values:
|
|
||||||
// - ME_NOTFOUND couldn't find a sharedlib that contains memory location
|
|
||||||
const char * DLLINTERNAL DLFNAME(void *memptr) {
|
|
||||||
Dl_info dli;
|
|
||||||
memset(&dli, 0, sizeof(dli));
|
|
||||||
if(dladdr(memptr, &dli))
|
|
||||||
return(dli.dli_fname);
|
|
||||||
else
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
// Implementation for win32 provided by Jussi Kivilinna <kijuhe00@rhea.otol.fi>:
|
|
||||||
//
|
|
||||||
// 1. Get memory location info on memptr with VirtualQuery.
|
|
||||||
// 2. Check if memory location info is valid and use MBI.AllocationBase
|
|
||||||
// as module start point.
|
|
||||||
// 3. Get module file name with GetModuleFileName.
|
|
||||||
//
|
|
||||||
// Simple and should work pretty much same way as 'dladdr' in linux.
|
|
||||||
// VirtualQuery and GetModuleFileName work even with win32s.
|
|
||||||
//
|
|
||||||
// Note that GetModuleFileName returns longfilenames rather than 8.3.
|
|
||||||
//
|
|
||||||
// Note also, the returned filename is local static storage, and should be
|
|
||||||
// copied by caller if it needs to keep it around.
|
|
||||||
//
|
|
||||||
// Also note, normalize_pathname() should really be done by the caller, but
|
|
||||||
// is done here to preserve "const char *" return consistent with linux
|
|
||||||
// version.
|
|
||||||
//
|
|
||||||
// Errno values:
|
|
||||||
// - ME_NOTFOUND couldn't find a DLL that contains memory location
|
|
||||||
const char * DLLINTERNAL DLFNAME(void *memptr) {
|
|
||||||
MEMORY_BASIC_INFORMATION MBI;
|
|
||||||
static char fname[PATH_MAX];
|
|
||||||
|
|
||||||
memset(fname, 0, sizeof(fname));
|
|
||||||
|
|
||||||
if(!VirtualQuery(memptr, &MBI, sizeof(MBI)))
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
if(MBI.State != MEM_COMMIT)
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
if(!MBI.AllocationBase)
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
|
|
||||||
// MSDN indicates that GetModuleFileName will leave string
|
|
||||||
// null-terminated, even if it's truncated because buffer is too small.
|
|
||||||
if(!GetModuleFileNameA((HMODULE)MBI.AllocationBase, fname, sizeof(fname)-1))
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
if(!fname[0])
|
|
||||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
||||||
|
|
||||||
normalize_pathname(fname);
|
|
||||||
return(fname);
|
|
||||||
}
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
// Normalize/standardize a pathname.
|
|
||||||
// - For win32, this involves:
|
|
||||||
// - Turning backslashes (\) into slashes (/), so that config files and
|
|
||||||
// Metamod internal code can be simpler and just use slashes (/).
|
|
||||||
// - Turning upper/mixed case into lowercase, since windows is
|
|
||||||
// non-case-sensitive.
|
|
||||||
// - For linux, this requires no work, as paths uses slashes (/) natively,
|
|
||||||
// and pathnames are case-sensitive.
|
|
||||||
void DLLINTERNAL normalize_pathname(char *path) {
|
|
||||||
char *cp;
|
|
||||||
|
|
||||||
META_DEBUG(8, ("normalize: %s", path));
|
|
||||||
for(cp=path; *cp; cp++) {
|
|
||||||
/*if(isupper(*cp))*/
|
|
||||||
*cp=tolower(*cp);
|
|
||||||
|
|
||||||
if(*cp=='\\')
|
|
||||||
*cp='/';
|
|
||||||
}
|
|
||||||
META_DEBUG(8, ("normalized: %s", path));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buffer pointed to by resolved_name is assumed to be able to store a
|
|
||||||
// string of PATH_MAX length.
|
|
||||||
char * DLLINTERNAL realpath(const char *file_name, char *resolved_name) {
|
|
||||||
int ret;
|
|
||||||
ret=GetFullPathNameA(file_name, PATH_MAX, resolved_name, NULL);
|
|
||||||
if(ret > PATH_MAX) {
|
|
||||||
errno=ENAMETOOLONG;
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
else if(ret > 0) {
|
|
||||||
HANDLE handle;
|
|
||||||
WIN32_FIND_DATAA find_data;
|
|
||||||
handle=FindFirstFileA(resolved_name, &find_data);
|
|
||||||
if(INVALID_HANDLE_VALUE == handle) {
|
|
||||||
errno=ENOENT;
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
FindClose(handle);
|
|
||||||
normalize_pathname(resolved_name);
|
|
||||||
return(resolved_name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
#endif /*_WIN32*/
|
|
||||||
|
|
||||||
|
|
||||||
// Determine whether the given memory location is valid (ie whether we
|
|
||||||
// should expect to be able to reference strings or functions at this
|
|
||||||
// location without segfaulting).
|
|
||||||
#ifdef linux
|
|
||||||
// Simulate this with dladdr. I'm not convinced this will be as generally
|
|
||||||
// applicable as the native windows routine below, but it should do what
|
|
||||||
// we need it for in this particular situation.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_NOTFOUND couldn't find a matching sharedlib for this ptr
|
|
||||||
mBOOL DLLINTERNAL IS_VALID_PTR(void *memptr) {
|
|
||||||
Dl_info dli;
|
|
||||||
memset(&dli, 0, sizeof(dli));
|
|
||||||
if(dladdr(memptr, &dli))
|
|
||||||
return(mTRUE);
|
|
||||||
else
|
|
||||||
RETURN_ERRNO(mFALSE, ME_NOTFOUND);
|
|
||||||
}
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
// Use the native windows routine IsBadCodePtr.
|
|
||||||
// meta_errno values:
|
|
||||||
// - ME_BADMEMPTR not a valid memory pointer
|
|
||||||
mBOOL DLLINTERNAL IS_VALID_PTR(void *memptr) {
|
|
||||||
if(IsBadCodePtr((FARPROC) memptr))
|
|
||||||
RETURN_ERRNO(mFALSE, ME_BADMEMPTR);
|
|
||||||
else
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
// This used to be OS-dependent, as it used a SEGV signal handler under
|
|
||||||
// linux, but that was removed because (a) it masked legitimate segfaults
|
|
||||||
// in plugin commands and produced confusing output ("plugin has been
|
|
||||||
// unloaded", when really it segfaultd), and (b) wasn't necessary since
|
|
||||||
// IS_VALID_PTR() should cover the situation.
|
|
||||||
mBOOL DLLINTERNAL os_safe_call(REG_CMD_FN pfn) {
|
|
||||||
// try and see if this is a valid memory location
|
|
||||||
if(!IS_VALID_PTR((void *) pfn))
|
|
||||||
// meta_errno should be already set in is_valid_ptr()
|
|
||||||
return(mFALSE);
|
|
||||||
|
|
||||||
pfn();
|
|
||||||
return(mTRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,341 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
|
||||||
*
|
|
||||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// enable extra routines in system header files, like dladdr
|
|
||||||
# ifndef _GNU_SOURCE
|
|
||||||
# define _GNU_SOURCE
|
|
||||||
# endif
|
|
||||||
#include <dlfcn.h> // dlopen, dladdr, etc
|
|
||||||
#include <signal.h> // sigaction, etc
|
|
||||||
#include <setjmp.h> // sigsetjmp, longjmp, etc
|
|
||||||
#include <sys/mman.h> // mmap, munmap, mprotect, etc
|
|
||||||
#include <link.h>
|
|
||||||
#include <elf.h>
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "osdep_p.h" // me
|
|
||||||
#include "support_meta.h" // STRNCPY
|
|
||||||
|
|
||||||
|
|
||||||
// On linux manually search for exports from dynamic library file.
|
|
||||||
// --Jussi Kivilinna
|
|
||||||
static jmp_buf signal_jmp_buf;
|
|
||||||
|
|
||||||
// Signal handler for is_gamedll()
|
|
||||||
static void signal_handler_sigsegv(int) {
|
|
||||||
/*
|
|
||||||
* GLIBC 2.11+ intercept longjmp with __longjmp_chk. However we want
|
|
||||||
* binary compability with older versions of GLIBC.
|
|
||||||
*/
|
|
||||||
#ifdef __amd64__
|
|
||||||
__asm__ volatile(".symver __longjmp_chk,longjmp@GLIBC_2.2.5"
|
|
||||||
:
|
|
||||||
:"r"(&signal_jmp_buf)
|
|
||||||
:"memory");
|
|
||||||
#else
|
|
||||||
__asm__ volatile(".symver __longjmp_chk,longjmp@GLIBC_2.0"
|
|
||||||
:
|
|
||||||
:"r"(&signal_jmp_buf)
|
|
||||||
:"memory");
|
|
||||||
#endif /*__amd64__*/
|
|
||||||
longjmp(signal_jmp_buf, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define invalid_elf_ptr(x) (((unsigned long)&(x)) > file_end - 1)
|
|
||||||
#define invalid_elf_offset(x) (((unsigned long)(x)) > filesize - 1)
|
|
||||||
#define elf_error_exit() \
|
|
||||||
do { \
|
|
||||||
sigaction(SIGSEGV, &oldaction, 0); \
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): Invalid ELF.", filename)); \
|
|
||||||
munmap(ehdr, filesize); \
|
|
||||||
return(mFALSE); \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
mBOOL DLLINTERNAL is_gamedll(const char *filename) {
|
|
||||||
// When these are not static there are some mysterious hidden bugs that I can't find/solve.
|
|
||||||
// So this is simple workaround.
|
|
||||||
static struct sigaction action;
|
|
||||||
static struct sigaction oldaction;
|
|
||||||
static ElfW(Ehdr) * ehdr = 0;
|
|
||||||
static ElfW(Shdr) * shdr = 0;
|
|
||||||
static ElfW(Sym) * symtab = 0;
|
|
||||||
static char * strtab = 0;
|
|
||||||
static FILE * pf = 0;
|
|
||||||
static unsigned long filesize = 0;
|
|
||||||
static unsigned long strtab_size = 0;
|
|
||||||
static unsigned long nsyms = 0;
|
|
||||||
static unsigned long i = 0;
|
|
||||||
static unsigned long file_end = 0;
|
|
||||||
static char * funcname = 0;
|
|
||||||
static int has_GiveFnptrsToDll = 0;
|
|
||||||
static int has_GetEntityAPI2 = 0;
|
|
||||||
static int has_GetEntityAPI = 0;
|
|
||||||
|
|
||||||
ehdr = 0;
|
|
||||||
shdr = 0;
|
|
||||||
symtab = 0;
|
|
||||||
strtab = 0;
|
|
||||||
pf = 0;
|
|
||||||
filesize = 0;
|
|
||||||
file_end = 0;
|
|
||||||
strtab_size = 0;
|
|
||||||
nsyms = 0;
|
|
||||||
i = 0;
|
|
||||||
funcname = 0;
|
|
||||||
has_GiveFnptrsToDll = 0;
|
|
||||||
has_GetEntityAPI2 = 0;
|
|
||||||
has_GetEntityAPI = 0;
|
|
||||||
|
|
||||||
// Try open file and get filesize
|
|
||||||
if((pf = fopen(filename, "rb"))) {
|
|
||||||
fseek(pf, 0, SEEK_END);
|
|
||||||
filesize = ftell(pf);
|
|
||||||
fseek(pf, 0, SEEK_SET);
|
|
||||||
} else {
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): Failed, cannot fopen() file.", filename));
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that filesize is atleast size of ELF header!
|
|
||||||
if(filesize < sizeof(ElfW(Ehdr))) {
|
|
||||||
#ifdef __x86_64__
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): Failed, file is too small to be ELF64. [%i < %i]", filename, filesize, sizeof(ElfW(Ehdr))));
|
|
||||||
#else
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): Failed, file is too small to be ELF32. [%i < %i]", filename, filesize, sizeof(ElfW(Ehdr))));
|
|
||||||
#endif
|
|
||||||
fclose(pf);
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// mmap library for easy reading
|
|
||||||
ehdr = (ElfW(Ehdr) *)mmap(0, filesize, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(pf), 0);
|
|
||||||
file_end = (unsigned long)ehdr + filesize;
|
|
||||||
|
|
||||||
// not needed anymore
|
|
||||||
fclose(pf);
|
|
||||||
|
|
||||||
// check if mmap was successful
|
|
||||||
if(!ehdr || (void*)ehdr==(void*)-1) {
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): Failed, mmap() [0x%x]", filename, ehdr));
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//In case that ELF file is incomplete (because bad upload etc), we protect memory-mapping access with signal-handler
|
|
||||||
if(!setjmp(signal_jmp_buf)) {
|
|
||||||
memset(&action, 0, sizeof(struct sigaction));
|
|
||||||
memset(&oldaction, 0, sizeof(struct sigaction));
|
|
||||||
|
|
||||||
// Not returning from signal, set SIGSEGV handler.
|
|
||||||
action.sa_handler = signal_handler_sigsegv;
|
|
||||||
action.sa_flags = SA_RESETHAND | SA_NODEFER;
|
|
||||||
sigemptyset(&action.sa_mask);
|
|
||||||
sigaction(SIGSEGV, &action, &oldaction);
|
|
||||||
} else {
|
|
||||||
// Reset signal handler.
|
|
||||||
sigaction(SIGSEGV, &oldaction, 0);
|
|
||||||
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): Failed, signal SIGSEGV.", filename));
|
|
||||||
|
|
||||||
munmap(ehdr, filesize);
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mm_strncmp((char *)ehdr, ELFMAG, SELFMAG) != 0 || ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
|
|
||||||
// Reset signal handler.
|
|
||||||
sigaction(SIGSEGV, &oldaction, 0);
|
|
||||||
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): Failed, file isn't ELF (%02x%02x%02x%02x:%x).", filename,
|
|
||||||
((char *)ehdr)[0], ((char *)ehdr)[1], ((char *)ehdr)[2], ((char *)ehdr)[3], ehdr->e_ident[EI_VERSION]));
|
|
||||||
|
|
||||||
munmap(ehdr, filesize);
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __x86_64__
|
|
||||||
// check if x86_64-shared-library
|
|
||||||
if(ehdr->e_ident[EI_CLASS] != ELFCLASS64 || ehdr->e_type != ET_DYN || ehdr->e_machine != EM_X86_64) {
|
|
||||||
// Reset signal handler.
|
|
||||||
sigaction(SIGSEGV, &oldaction, 0);
|
|
||||||
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): Failed, ELF isn't for target:x86_64. [%x:%x:%x]", filename,
|
|
||||||
ehdr->e_ident[EI_CLASS], ehdr->e_type, ehdr->e_machine));
|
|
||||||
|
|
||||||
munmap(ehdr, filesize);
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
// check if x86-shared-library
|
|
||||||
if(ehdr->e_ident[EI_CLASS] != ELFCLASS32 || ehdr->e_type != ET_DYN || ehdr->e_machine != EM_386) {
|
|
||||||
// Reset signal handler.
|
|
||||||
sigaction(SIGSEGV, &oldaction, 0);
|
|
||||||
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): Failed, ELF isn't for target:i386. [%x:%x:%x]", filename,
|
|
||||||
ehdr->e_ident[EI_CLASS], ehdr->e_type, ehdr->e_machine));
|
|
||||||
|
|
||||||
munmap(ehdr, filesize);
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//Get symtab and strtab info
|
|
||||||
shdr = (ElfW(Shdr) *)((char *)ehdr + ehdr->e_shoff);
|
|
||||||
if(invalid_elf_ptr(shdr[ehdr->e_shnum]))
|
|
||||||
elf_error_exit();
|
|
||||||
|
|
||||||
for(i = 0; i < ehdr->e_shnum; i++) {
|
|
||||||
// searching for dynamic linker symbol table
|
|
||||||
if(shdr[i].sh_type == SHT_DYNSYM) {
|
|
||||||
if(invalid_elf_offset(shdr[i].sh_offset) ||
|
|
||||||
invalid_elf_ptr(shdr[shdr[i].sh_link]) ||
|
|
||||||
invalid_elf_offset(shdr[shdr[i].sh_link].sh_offset) ||
|
|
||||||
invalid_elf_ptr(strtab[strtab_size]) ||
|
|
||||||
invalid_elf_ptr(symtab[nsyms]))
|
|
||||||
elf_error_exit();
|
|
||||||
|
|
||||||
symtab = (ElfW(Sym) *)((char *)ehdr + shdr[i].sh_offset);
|
|
||||||
strtab = (char *)((char *)ehdr + shdr[shdr[i].sh_link].sh_offset);
|
|
||||||
strtab_size = shdr[shdr[i].sh_link].sh_size;
|
|
||||||
nsyms = shdr[i].sh_size / shdr[i].sh_entsize;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!symtab) {
|
|
||||||
//Another method for finding symtab
|
|
||||||
for(i = 0; i < ehdr->e_shnum; i++) {
|
|
||||||
if(shdr[i].sh_type == SHT_SYMTAB) {
|
|
||||||
if(invalid_elf_offset(shdr[i].sh_offset) ||
|
|
||||||
invalid_elf_ptr(shdr[shdr[i].sh_link]) ||
|
|
||||||
invalid_elf_offset(shdr[shdr[i].sh_link].sh_offset) ||
|
|
||||||
invalid_elf_ptr(strtab[strtab_size]) ||
|
|
||||||
invalid_elf_ptr(symtab[nsyms]))
|
|
||||||
elf_error_exit();
|
|
||||||
|
|
||||||
symtab = (ElfW(Sym) *)((char *)ehdr + shdr[i].sh_offset);
|
|
||||||
strtab = (char *)((char *)ehdr + shdr[shdr[i].sh_link].sh_offset);
|
|
||||||
strtab_size = shdr[shdr[i].sh_link].sh_size;
|
|
||||||
nsyms = shdr[i].sh_size / shdr[i].sh_entsize;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!symtab) {
|
|
||||||
// Reset signal handler.
|
|
||||||
sigaction(SIGSEGV, &oldaction, 0);
|
|
||||||
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): Failed, couldn't locate symtab.", filename));
|
|
||||||
|
|
||||||
munmap(ehdr, filesize);
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Search symbols for exports
|
|
||||||
for(i = 0; i < nsyms; i++) {
|
|
||||||
#ifdef __x86_64__
|
|
||||||
// Export?
|
|
||||||
if(ELF64_ST_TYPE(symtab[i].st_info) != STT_FUNC || ELF64_ST_BIND(symtab[i].st_info) != STB_GLOBAL)
|
|
||||||
continue;
|
|
||||||
#else
|
|
||||||
// Export?
|
|
||||||
if(ELF32_ST_TYPE(symtab[i].st_info) != STT_FUNC || ELF32_ST_BIND(symtab[i].st_info) != STB_GLOBAL)
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// string outside strtab?
|
|
||||||
if(symtab[i].st_name <= 0 || symtab[i].st_name >= strtab_size)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
funcname = &strtab[symtab[i].st_name];
|
|
||||||
|
|
||||||
// Check
|
|
||||||
// Fast check for 'G' first
|
|
||||||
if(funcname[0] == 'G') {
|
|
||||||
// Collect export information
|
|
||||||
if(!has_GiveFnptrsToDll)
|
|
||||||
has_GiveFnptrsToDll = strmatch(funcname, "GiveFnptrsToDll");
|
|
||||||
if(!has_GetEntityAPI2)
|
|
||||||
has_GetEntityAPI2 = strmatch(funcname, "GetEntityAPI2");
|
|
||||||
if(!has_GetEntityAPI)
|
|
||||||
has_GetEntityAPI = strmatch(funcname, "GetEntityAPI");
|
|
||||||
}
|
|
||||||
// Check if metamod plugin
|
|
||||||
else if(funcname[0] == 'M') {
|
|
||||||
if(strmatch(funcname, "Meta_Init") ||
|
|
||||||
strmatch(funcname, "Meta_Query") ||
|
|
||||||
strmatch(funcname, "Meta_Attach") ||
|
|
||||||
strmatch(funcname, "Meta_Detach")) {
|
|
||||||
// Metamod plugin.. is not gamedll
|
|
||||||
META_DEBUG(5, ("is_gamedll(%s): Detected Metamod plugin, library exports [%s].", filename, funcname));
|
|
||||||
|
|
||||||
// Reset signal handler.
|
|
||||||
sigaction(SIGSEGV, &oldaction, 0);
|
|
||||||
|
|
||||||
munmap(ehdr, filesize);
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if gamedll
|
|
||||||
if(has_GiveFnptrsToDll && (has_GetEntityAPI2 || has_GetEntityAPI)) {
|
|
||||||
// This is gamedll!
|
|
||||||
META_DEBUG(5, ("is_gamedll(%s): Detected GameDLL.", filename));
|
|
||||||
|
|
||||||
// Reset signal handler.
|
|
||||||
sigaction(SIGSEGV, &oldaction, 0);
|
|
||||||
|
|
||||||
munmap(ehdr, filesize);
|
|
||||||
|
|
||||||
return(mTRUE);
|
|
||||||
} else {
|
|
||||||
META_DEBUG(5, ("is_gamedll(%s): Library isn't GameDLL.", filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset signal handler.
|
|
||||||
sigaction(SIGSEGV, &oldaction, 0);
|
|
||||||
|
|
||||||
munmap(ehdr, filesize);
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
@@ -1,225 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
|
||||||
*
|
|
||||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "osdep_p.h" // me
|
|
||||||
#include "support_meta.h" // STRNCPY
|
|
||||||
|
|
||||||
//check for invalid handle values
|
|
||||||
#define is_invalid_handle(X) ((X)==0 || (X)==INVALID_HANDLE_VALUE)
|
|
||||||
|
|
||||||
//relative virtual address to virtual address
|
|
||||||
#define rva_to_va(base, rva) ((unsigned long)base + (unsigned long)rva)
|
|
||||||
//virtual address to relative virtual address
|
|
||||||
#define va_to_rva(base, va) ((unsigned long)va - (unsigned long)base)
|
|
||||||
|
|
||||||
//
|
|
||||||
static unsigned long DLLINTERNAL_NOVIS va_to_mapaddr(void * mapview, IMAGE_SECTION_HEADER * sections, int num_sects, unsigned long vaddr) {
|
|
||||||
for(int i = 0; i < num_sects; i++)
|
|
||||||
if(vaddr >= sections[i].VirtualAddress && vaddr < sections[i].VirtualAddress + sections[i].SizeOfRawData)
|
|
||||||
return(rva_to_va(mapview, (vaddr - sections[i].VirtualAddress + sections[i].PointerToRawData)));
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks module signatures and return ntheaders pointer for valid module
|
|
||||||
static IMAGE_NT_HEADERS * DLLINTERNAL_NOVIS get_ntheaders(void * mapview) {
|
|
||||||
union {
|
|
||||||
unsigned long mem;
|
|
||||||
IMAGE_DOS_HEADER * dos;
|
|
||||||
IMAGE_NT_HEADERS * pe;
|
|
||||||
} mem;
|
|
||||||
|
|
||||||
//Check if valid dos header
|
|
||||||
mem.mem = (unsigned long)mapview;
|
|
||||||
if(IsBadReadPtr(mem.dos, sizeof(*mem.dos)) || mem.dos->e_magic != IMAGE_DOS_SIGNATURE)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
//Get and check pe header
|
|
||||||
mem.mem = rva_to_va(mapview, mem.dos->e_lfanew);
|
|
||||||
if(IsBadReadPtr(mem.pe, sizeof(*mem.pe)) || mem.pe->Signature != IMAGE_NT_SIGNATURE)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
return(mem.pe);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns export table for valid module
|
|
||||||
static IMAGE_EXPORT_DIRECTORY * DLLINTERNAL_NOVIS get_export_table(void * mapview, IMAGE_NT_HEADERS * ntheaders, IMAGE_SECTION_HEADER * sections, int num_sects) {
|
|
||||||
union {
|
|
||||||
unsigned long mem;
|
|
||||||
void * pvoid;
|
|
||||||
IMAGE_DOS_HEADER * dos;
|
|
||||||
IMAGE_NT_HEADERS * pe;
|
|
||||||
IMAGE_EXPORT_DIRECTORY * export_dir;
|
|
||||||
} mem;
|
|
||||||
|
|
||||||
mem.pe = ntheaders;
|
|
||||||
|
|
||||||
//Check for exports
|
|
||||||
if(!mem.pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
mem.mem = va_to_mapaddr(mapview, sections, num_sects, mem.pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
|
||||||
if(IsBadReadPtr(mem.export_dir, sizeof(*mem.export_dir)))
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
return(mem.export_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
mBOOL DLLINTERNAL is_gamedll(const char *filename) {
|
|
||||||
HANDLE hFile;
|
|
||||||
HANDLE hMap;
|
|
||||||
void * mapview;
|
|
||||||
IMAGE_NT_HEADERS * ntheaders;
|
|
||||||
IMAGE_SECTION_HEADER * sections;
|
|
||||||
int num_sects;
|
|
||||||
IMAGE_EXPORT_DIRECTORY * exports;
|
|
||||||
|
|
||||||
int has_GiveFnptrsToDll = 0;
|
|
||||||
int has_GetEntityAPI2 = 0;
|
|
||||||
int has_GetEntityAPI = 0;
|
|
||||||
|
|
||||||
// Try open file for read
|
|
||||||
hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if(is_invalid_handle(hFile)) {
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): CreateFile() failed.", filename));
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
|
||||||
if(is_invalid_handle(hMap)) {
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): CreateFileMapping() failed.", filename));
|
|
||||||
CloseHandle(hFile);
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
mapview = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
|
||||||
if(!mapview) {
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): MapViewOfFile() failed.", filename));
|
|
||||||
CloseHandle(hMap);
|
|
||||||
CloseHandle(hFile);
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ntheaders = get_ntheaders(mapview);
|
|
||||||
if(!ntheaders) {
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): get_ntheaders() failed.", filename));
|
|
||||||
UnmapViewOfFile(mapview);
|
|
||||||
CloseHandle(hMap);
|
|
||||||
CloseHandle(hFile);
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Sections for va_to_mapaddr function
|
|
||||||
sections = IMAGE_FIRST_SECTION(ntheaders);
|
|
||||||
num_sects = ntheaders->FileHeader.NumberOfSections;
|
|
||||||
if(IsBadReadPtr(sections, num_sects * sizeof(IMAGE_SECTION_HEADER))) {
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): IMAGE_FIRST_SECTION() failed.", filename));
|
|
||||||
UnmapViewOfFile(mapview);
|
|
||||||
CloseHandle(hMap);
|
|
||||||
CloseHandle(hFile);
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
exports = get_export_table(mapview, ntheaders, sections, num_sects);
|
|
||||||
if(!exports) {
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): get_export_table() failed.", filename));
|
|
||||||
UnmapViewOfFile(mapview);
|
|
||||||
CloseHandle(hMap);
|
|
||||||
CloseHandle(hFile);
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
unsigned long * names = (unsigned long *)va_to_mapaddr(mapview, sections, num_sects, exports->AddressOfNames);
|
|
||||||
if(IsBadReadPtr(names, exports->NumberOfNames * sizeof(unsigned long))) {
|
|
||||||
META_DEBUG(3, ("is_gamedll(%s): Pointer to exported function names is invalid.", filename));
|
|
||||||
UnmapViewOfFile(mapview);
|
|
||||||
CloseHandle(hMap);
|
|
||||||
CloseHandle(hFile);
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < exports->NumberOfNames; i++) {
|
|
||||||
//get function name with valid address
|
|
||||||
char * funcname = (char *)va_to_mapaddr(mapview, sections, num_sects, names[i]);
|
|
||||||
if(IsBadStringPtrA(funcname, 128))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Check
|
|
||||||
// Fast check for 'G' first
|
|
||||||
if(funcname[0] == 'G') {
|
|
||||||
// Collect export information
|
|
||||||
if(!has_GiveFnptrsToDll)
|
|
||||||
has_GiveFnptrsToDll = strmatch(funcname, "GiveFnptrsToDll");
|
|
||||||
if(!has_GetEntityAPI2)
|
|
||||||
has_GetEntityAPI2 = strmatch(funcname, "GetEntityAPI2");
|
|
||||||
if(!has_GetEntityAPI)
|
|
||||||
has_GetEntityAPI = strmatch(funcname, "GetEntityAPI");
|
|
||||||
}
|
|
||||||
// Check if metamod plugin
|
|
||||||
else if(funcname[0] == 'M') {
|
|
||||||
if(strmatch(funcname, "Meta_Init") ||
|
|
||||||
strmatch(funcname, "Meta_Query") ||
|
|
||||||
strmatch(funcname, "Meta_Attach") ||
|
|
||||||
strmatch(funcname, "Meta_Detach")) {
|
|
||||||
// Metamod plugin.. is not gamedll
|
|
||||||
META_DEBUG(5, ("is_gamedll(%s): Detected Metamod plugin, library exports [%s].", filename, funcname));
|
|
||||||
|
|
||||||
UnmapViewOfFile(mapview);
|
|
||||||
CloseHandle(hMap);
|
|
||||||
CloseHandle(hFile);
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UnmapViewOfFile(mapview);
|
|
||||||
CloseHandle(hMap);
|
|
||||||
CloseHandle(hFile);
|
|
||||||
|
|
||||||
// Check if gamedll
|
|
||||||
if(has_GiveFnptrsToDll && (has_GetEntityAPI2 || has_GetEntityAPI)) {
|
|
||||||
// This is gamedll!
|
|
||||||
META_DEBUG(5, ("is_gamedll(%s): Detected GameDLL.", filename));
|
|
||||||
|
|
||||||
return(mTRUE);
|
|
||||||
} else {
|
|
||||||
META_DEBUG(5, ("is_gamedll(%s): Library isn't GameDLL.", filename));
|
|
||||||
|
|
||||||
return(mFALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,234 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
|
||||||
*
|
|
||||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#ifndef __USE_GNU
|
|
||||||
#define __USE_GNU
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#define PAGE_SIZE 4096UL
|
|
||||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
|
||||||
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <link.h>
|
|
||||||
|
|
||||||
#include "osdep.h"
|
|
||||||
#include "osdep_p.h"
|
|
||||||
#include "log_meta.h" // META_LOG, etc
|
|
||||||
#include "support_meta.h"
|
|
||||||
|
|
||||||
//
|
|
||||||
// Linux code for dynamic linkents
|
|
||||||
// -- by Jussi Kivilinna
|
|
||||||
//
|
|
||||||
|
|
||||||
//opcode, e9, + sizeof pointer
|
|
||||||
#define BYTES_SIZE (1 + sizeof(void*))
|
|
||||||
|
|
||||||
typedef void * (*dlsym_func)(void * module, const char * funcname);
|
|
||||||
|
|
||||||
static void * gamedll_module_handle = 0;
|
|
||||||
static void * metamod_module_handle = 0;
|
|
||||||
|
|
||||||
//pointer to original dlsym
|
|
||||||
static dlsym_func dlsym_original;
|
|
||||||
|
|
||||||
//contains jmp to replacement_dlsym @dlsym_original
|
|
||||||
static unsigned char dlsym_new_bytes[BYTES_SIZE];
|
|
||||||
|
|
||||||
//contains original bytes of dlsym
|
|
||||||
static unsigned char dlsym_old_bytes[BYTES_SIZE];
|
|
||||||
|
|
||||||
//Mutex for our protection
|
|
||||||
static pthread_mutex_t mutex_replacement_dlsym = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
|
||||||
|
|
||||||
//constructs new jmp forwarder
|
|
||||||
inline void construct_jmp_instruction(void *x, void *place, void* target)
|
|
||||||
{
|
|
||||||
((unsigned char *)x)[0] = 0xe9;
|
|
||||||
*(unsigned long *)((char *)x + 1) = (unsigned long)target - ((unsigned long)place + 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
//checks if pointer x points to jump forwarder
|
|
||||||
inline bool is_code_trampoline_jmp_opcode(void *x)
|
|
||||||
{
|
|
||||||
return (((unsigned char *)x)[0] == 0xff || ((unsigned char *)x)[1] == 0x25);
|
|
||||||
}
|
|
||||||
|
|
||||||
//extracts pointer from "jmp dword ptr[pointer]"
|
|
||||||
inline void * extract_function_pointer_from_trampoline_jmp(void *x)
|
|
||||||
{
|
|
||||||
return (**(void***)((char *)(x) + 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
//restores old dlsym
|
|
||||||
//
|
|
||||||
inline void DLLINTERNAL restore_original_dlsym(void)
|
|
||||||
{
|
|
||||||
//Copy old dlsym bytes back
|
|
||||||
memcpy((void*)dlsym_original, dlsym_old_bytes, BYTES_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
//resets new dlsym
|
|
||||||
//
|
|
||||||
inline void DLLINTERNAL reset_dlsym_hook(void)
|
|
||||||
{
|
|
||||||
//Copy new dlsym bytes back
|
|
||||||
memcpy((void*)dlsym_original, dlsym_new_bytes, BYTES_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Replacement dlsym function
|
|
||||||
//
|
|
||||||
static void * __replacement_dlsym(void * module, const char * funcname)
|
|
||||||
{
|
|
||||||
//these are needed in case dlsym calls dlsym, default one doesn't do
|
|
||||||
//it but some LD_PRELOADed library that hooks dlsym might actually
|
|
||||||
//do so.
|
|
||||||
static int is_original_restored = 0;
|
|
||||||
int was_original_restored = is_original_restored;
|
|
||||||
|
|
||||||
//Lock before modifing original dlsym
|
|
||||||
pthread_mutex_lock(&mutex_replacement_dlsym);
|
|
||||||
|
|
||||||
//restore old dlsym
|
|
||||||
if(!is_original_restored)
|
|
||||||
{
|
|
||||||
restore_original_dlsym();
|
|
||||||
|
|
||||||
is_original_restored = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if we should hook this call
|
|
||||||
if(module != metamod_module_handle || !metamod_module_handle || !gamedll_module_handle)
|
|
||||||
{
|
|
||||||
//no metamod/gamedll module? should we remove hook now?
|
|
||||||
void * retval = dlsym_original(module, funcname);
|
|
||||||
|
|
||||||
if(metamod_module_handle && gamedll_module_handle)
|
|
||||||
{
|
|
||||||
if(!was_original_restored)
|
|
||||||
{
|
|
||||||
//reset dlsym hook
|
|
||||||
reset_dlsym_hook();
|
|
||||||
|
|
||||||
is_original_restored = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//no metamod/gamedll module? should we remove hook now by not reseting it back?
|
|
||||||
}
|
|
||||||
|
|
||||||
//unlock
|
|
||||||
pthread_mutex_unlock(&mutex_replacement_dlsym);
|
|
||||||
|
|
||||||
return(retval);
|
|
||||||
}
|
|
||||||
|
|
||||||
//dlsym on metamod module
|
|
||||||
void * func = dlsym_original(module, funcname);
|
|
||||||
|
|
||||||
if(!func)
|
|
||||||
{
|
|
||||||
//function not in metamod module, try gamedll
|
|
||||||
func = dlsym_original(gamedll_module_handle, funcname);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!was_original_restored)
|
|
||||||
{
|
|
||||||
//reset dlsym hook
|
|
||||||
reset_dlsym_hook();
|
|
||||||
|
|
||||||
is_original_restored = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//unlock
|
|
||||||
pthread_mutex_unlock(&mutex_replacement_dlsym);
|
|
||||||
|
|
||||||
return(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Initialize
|
|
||||||
//
|
|
||||||
int DLLINTERNAL init_linkent_replacement(DLHANDLE MetamodHandle, DLHANDLE GameDllHandle)
|
|
||||||
{
|
|
||||||
metamod_module_handle = MetamodHandle;
|
|
||||||
gamedll_module_handle = GameDllHandle;
|
|
||||||
|
|
||||||
// dlsym is already known to be pointing to valid function, we loaded gamedll using it earlier!
|
|
||||||
void * sym_ptr = (void*)&dlsym;
|
|
||||||
while(is_code_trampoline_jmp_opcode(sym_ptr)) {
|
|
||||||
sym_ptr = extract_function_pointer_from_trampoline_jmp(sym_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
dlsym_original = (dlsym_func)sym_ptr;
|
|
||||||
|
|
||||||
//Backup old bytes of "dlsym" function
|
|
||||||
memcpy(dlsym_old_bytes, (void*)dlsym_original, BYTES_SIZE);
|
|
||||||
|
|
||||||
//Construct new bytes: "jmp offset[replacement_sendto] @ sendto_original"
|
|
||||||
construct_jmp_instruction((void*)&dlsym_new_bytes[0], (void*)dlsym_original, (void*)&__replacement_dlsym);
|
|
||||||
|
|
||||||
//Check if bytes overlap page border.
|
|
||||||
unsigned long start_of_page = PAGE_ALIGN((long)dlsym_original) - PAGE_SIZE;
|
|
||||||
unsigned long size_of_pages = 0;
|
|
||||||
|
|
||||||
if((unsigned long)dlsym_original + BYTES_SIZE > PAGE_ALIGN((unsigned long)dlsym_original))
|
|
||||||
{
|
|
||||||
//bytes are located on two pages
|
|
||||||
size_of_pages = PAGE_SIZE*2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//bytes are located entirely on one page.
|
|
||||||
size_of_pages = PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Remove PROT_READ restriction
|
|
||||||
if(mprotect((void*)start_of_page, size_of_pages, PROT_READ|PROT_WRITE|PROT_EXEC))
|
|
||||||
{
|
|
||||||
META_ERROR("Couldn't initialize dynamic linkents, mprotect failed: %i. Exiting...", errno);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Write our own jmp-forwarder on "dlsym"
|
|
||||||
reset_dlsym_hook();
|
|
||||||
|
|
||||||
//done
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
@@ -1,245 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
|
||||||
*
|
|
||||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
#include "osdep.h"
|
|
||||||
|
|
||||||
#include "log_meta.h" // META_LOG, etc
|
|
||||||
#include "support_meta.h"
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// Win32 code for dynamic linkents
|
|
||||||
// -- by Jussi Kivilinna
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Reads metamod.dll and game.dll function export tables and combines theim to
|
|
||||||
// single table that replaces metamod.dll's original table.
|
|
||||||
//
|
|
||||||
|
|
||||||
typedef struct sort_names_s {
|
|
||||||
unsigned long name;
|
|
||||||
unsigned short nameOrdinal;
|
|
||||||
} sort_names_t;
|
|
||||||
|
|
||||||
//relative virtual address to virtual address
|
|
||||||
#define rva_to_va(base, rva) ((unsigned long)base + (unsigned long)rva)
|
|
||||||
//virtual address to relative virtual address
|
|
||||||
#define va_to_rva(base, va) ((unsigned long)va - (unsigned long)base)
|
|
||||||
|
|
||||||
//
|
|
||||||
// Checks module signatures and return ntheaders pointer for valid module
|
|
||||||
//
|
|
||||||
static IMAGE_NT_HEADERS * DLLINTERNAL_NOVIS get_ntheaders(HMODULE module)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
unsigned long mem;
|
|
||||||
IMAGE_DOS_HEADER * dos;
|
|
||||||
IMAGE_NT_HEADERS * pe;
|
|
||||||
} mem;
|
|
||||||
|
|
||||||
//Check if valid dos header
|
|
||||||
mem.mem = (unsigned long)module;
|
|
||||||
if(IsBadReadPtr(mem.dos, sizeof(*mem.dos)) || mem.dos->e_magic != IMAGE_DOS_SIGNATURE)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
//Get and check pe header
|
|
||||||
mem.mem = rva_to_va(module, mem.dos->e_lfanew);
|
|
||||||
if(IsBadReadPtr(mem.pe, sizeof(*mem.pe)) || mem.pe->Signature != IMAGE_NT_SIGNATURE)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
return(mem.pe);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Returns export table for valid module
|
|
||||||
//
|
|
||||||
static IMAGE_EXPORT_DIRECTORY * DLLINTERNAL_NOVIS get_export_table(HMODULE module)
|
|
||||||
{
|
|
||||||
union {
|
|
||||||
unsigned long mem;
|
|
||||||
void * pvoid;
|
|
||||||
IMAGE_DOS_HEADER * dos;
|
|
||||||
IMAGE_NT_HEADERS * pe;
|
|
||||||
IMAGE_EXPORT_DIRECTORY * export_dir;
|
|
||||||
} mem;
|
|
||||||
|
|
||||||
//Check module
|
|
||||||
mem.pe = get_ntheaders(module);
|
|
||||||
if(!mem.pe)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
//Check for exports
|
|
||||||
if(!mem.pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
mem.mem = rva_to_va(module, mem.pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
|
||||||
if(IsBadReadPtr(mem.export_dir, sizeof(*mem.export_dir)))
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
return(mem.export_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Sort function for qsort
|
|
||||||
//
|
|
||||||
static int sort_names_list(const sort_names_t * A, const sort_names_t * B)
|
|
||||||
{
|
|
||||||
const char * str_A = (const char *)A->name;
|
|
||||||
const char * str_B = (const char *)B->name;
|
|
||||||
|
|
||||||
return(mm_strcmp(str_A, str_B));
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Combines moduleMM and moduleGame export tables and replaces moduleMM table with new one
|
|
||||||
//
|
|
||||||
static int DLLINTERNAL_NOVIS combine_module_export_tables(HMODULE moduleMM, HMODULE moduleGame)
|
|
||||||
{
|
|
||||||
IMAGE_EXPORT_DIRECTORY * exportMM;
|
|
||||||
IMAGE_EXPORT_DIRECTORY * exportGame;
|
|
||||||
|
|
||||||
unsigned long newNumberOfFunctions;
|
|
||||||
unsigned long newNumberOfNames;
|
|
||||||
unsigned long * newFunctions;
|
|
||||||
unsigned long * newNames;
|
|
||||||
unsigned short * newNameOrdinals;
|
|
||||||
sort_names_t * newSort;
|
|
||||||
|
|
||||||
unsigned long i;
|
|
||||||
unsigned long u;
|
|
||||||
unsigned long funcCount;
|
|
||||||
unsigned long nameCount;
|
|
||||||
unsigned long listFix;
|
|
||||||
|
|
||||||
//Get export tables
|
|
||||||
exportMM = get_export_table(moduleMM);
|
|
||||||
exportGame = get_export_table(moduleGame);
|
|
||||||
if(!exportMM || !exportGame)
|
|
||||||
{
|
|
||||||
META_ERROR("Couldn't initialize dynamic linkents, exportMM: %i, exportGame: %i. Exiting...", exportMM, exportGame);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
//setup new export table
|
|
||||||
newNumberOfFunctions = exportMM->NumberOfFunctions + exportGame->NumberOfFunctions;
|
|
||||||
newNumberOfNames = exportMM->NumberOfNames + exportGame->NumberOfNames;
|
|
||||||
|
|
||||||
//alloc lists
|
|
||||||
*(void**)&newFunctions = calloc(1, newNumberOfFunctions * sizeof(*newFunctions));
|
|
||||||
*(void**)&newSort = calloc(1, newNumberOfNames * sizeof(*newSort));
|
|
||||||
|
|
||||||
//copy moduleMM to new export
|
|
||||||
for(funcCount = 0; funcCount < exportMM->NumberOfFunctions; funcCount++)
|
|
||||||
newFunctions[funcCount] = rva_to_va(moduleMM, ((unsigned long*)rva_to_va(moduleMM, exportMM->AddressOfFunctions))[funcCount]);
|
|
||||||
for(nameCount = 0; nameCount < exportMM->NumberOfNames; nameCount++)
|
|
||||||
{
|
|
||||||
//fix name address
|
|
||||||
newSort[nameCount].name = rva_to_va(moduleMM, ((unsigned long*)rva_to_va(moduleMM, exportMM->AddressOfNames))[nameCount]);
|
|
||||||
//ordinal is index to function list
|
|
||||||
newSort[nameCount].nameOrdinal = ((unsigned short *)rva_to_va(moduleMM, exportMM->AddressOfNameOrdinals))[nameCount];
|
|
||||||
}
|
|
||||||
|
|
||||||
//copy moduleGame to new export
|
|
||||||
for(i = 0; i < exportGame->NumberOfFunctions; i++)
|
|
||||||
newFunctions[funcCount + i] = rva_to_va(moduleGame, ((unsigned long*)rva_to_va(moduleGame, exportGame->AddressOfFunctions))[i]);
|
|
||||||
for(i = 0, listFix = 0; i < exportGame->NumberOfNames; i++)
|
|
||||||
{
|
|
||||||
const char * name = (const char *)rva_to_va(moduleGame, ((unsigned long*)rva_to_va(moduleGame, exportGame->AddressOfNames))[i]);
|
|
||||||
//Check if name already in the list
|
|
||||||
for(u = 0; u < nameCount; u++)
|
|
||||||
{
|
|
||||||
if(!strcasecmp(name, (const char*)newSort[u].name))
|
|
||||||
{
|
|
||||||
listFix -= 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(u < nameCount) //already in the list.. skip
|
|
||||||
continue;
|
|
||||||
|
|
||||||
newSort[nameCount + i + listFix].name = (unsigned long)name;
|
|
||||||
newSort[nameCount + i + listFix].nameOrdinal = (unsigned short)funcCount + ((unsigned short *)rva_to_va(moduleGame, exportGame->AddressOfNameOrdinals))[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
//set new number
|
|
||||||
newNumberOfNames = nameCount + i + listFix;
|
|
||||||
|
|
||||||
//sort names list
|
|
||||||
qsort(newSort, newNumberOfNames, sizeof(*newSort), (int(*)(const void*, const void*))&sort_names_list);
|
|
||||||
|
|
||||||
//make newNames and newNameOrdinals lists (VirtualAlloc so we dont waste heap memory to stuff that isn't freed)
|
|
||||||
*(void**)&newNames = VirtualAlloc(0, newNumberOfNames * sizeof(*newNames), MEM_COMMIT, PAGE_READWRITE);
|
|
||||||
*(void**)&newNameOrdinals = VirtualAlloc(0, newNumberOfNames * sizeof(*newNameOrdinals), MEM_COMMIT, PAGE_READWRITE);
|
|
||||||
|
|
||||||
for(i = 0; i < newNumberOfNames; i++)
|
|
||||||
{
|
|
||||||
newNames[i] = newSort[i].name;
|
|
||||||
newNameOrdinals[i] = newSort[i].nameOrdinal;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(newSort);
|
|
||||||
|
|
||||||
//translate VAs to RVAs
|
|
||||||
for(i = 0; i < newNumberOfFunctions; i++)
|
|
||||||
newFunctions[i] = va_to_rva(moduleMM, newFunctions[i]);
|
|
||||||
for(i = 0; i < newNumberOfNames; i++)
|
|
||||||
{
|
|
||||||
newNames[i] = va_to_rva(moduleMM, newNames[i]);
|
|
||||||
newNameOrdinals[i] = (unsigned short)va_to_rva(moduleMM, newNameOrdinals[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD OldProtect;
|
|
||||||
if(!VirtualProtect(exportMM, sizeof(*exportMM), PAGE_READWRITE, &OldProtect))
|
|
||||||
{
|
|
||||||
META_ERROR("Couldn't initialize dynamic linkents, VirtualProtect failed: %i. Exiting...", GetLastError());
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
exportMM->Base = 1;
|
|
||||||
exportMM->NumberOfFunctions = newNumberOfFunctions;
|
|
||||||
exportMM->NumberOfNames = newNumberOfNames;
|
|
||||||
*(unsigned long*)&(exportMM->AddressOfFunctions) = va_to_rva(moduleMM, newFunctions);
|
|
||||||
*(unsigned long*)&(exportMM->AddressOfNames) = va_to_rva(moduleMM, newNames);
|
|
||||||
*(unsigned long*)&(exportMM->AddressOfNameOrdinals) = va_to_rva(moduleMM, newNameOrdinals);
|
|
||||||
|
|
||||||
VirtualProtect(exportMM, sizeof(*exportMM), OldProtect, &OldProtect);
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// ...
|
|
||||||
//
|
|
||||||
int DLLINTERNAL init_linkent_replacement(DLHANDLE moduleMetamod, DLHANDLE moduleGame)
|
|
||||||
{
|
|
||||||
return(combine_module_export_tables(moduleMetamod, moduleGame));
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
|
||||||
*
|
|
||||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef linux
|
|
||||||
// enable extra routines in system header files, like dladdr
|
|
||||||
# ifndef _GNU_SOURCE
|
|
||||||
# define _GNU_SOURCE
|
|
||||||
# endif
|
|
||||||
#include <dlfcn.h> // dlopen, dladdr, etc
|
|
||||||
#endif /* linux */
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "osdep_p.h" // me
|
|
||||||
#include "support_meta.h" // STRNCPY
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
// MSVC doesn't provide "dirent.h" header. These functions wrap opendir/readdir/closedir
|
|
||||||
// functions to FindFirst/FindNext/FindClose win32api-functions.
|
|
||||||
DIR * DLLINTERNAL my_opendir(const char *path)
|
|
||||||
{
|
|
||||||
char search_path[MAX_PATH];
|
|
||||||
DIR *dir;
|
|
||||||
|
|
||||||
// Add wildcards to path
|
|
||||||
safevoid_snprintf(search_path, sizeof(search_path), "%s\\*.*", path);
|
|
||||||
|
|
||||||
// Get memory for new DIR object
|
|
||||||
dir = (DIR*)calloc(1, sizeof(DIR));
|
|
||||||
|
|
||||||
// Start searching
|
|
||||||
dir->handle = FindFirstFileA(search_path, &dir->find_data);
|
|
||||||
if(dir->handle == INVALID_HANDLE_VALUE) {
|
|
||||||
free(dir);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Found file
|
|
||||||
dir->not_found = 0;
|
|
||||||
|
|
||||||
return(dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct dirent * DLLINTERNAL my_readdir(DIR *dir)
|
|
||||||
{
|
|
||||||
// If not found stop
|
|
||||||
if(!dir || dir->not_found)
|
|
||||||
return(0);
|
|
||||||
|
|
||||||
// Set filename
|
|
||||||
STRNCPY(dir->ent.d_name, dir->find_data.cFileName, sizeof(dir->ent.d_name));
|
|
||||||
|
|
||||||
// Search next
|
|
||||||
dir->not_found = !FindNextFileA(dir->handle, &dir->find_data);
|
|
||||||
|
|
||||||
return(&dir->ent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DLLINTERNAL my_closedir(DIR *dir)
|
|
||||||
{
|
|
||||||
if(!dir)
|
|
||||||
return;
|
|
||||||
|
|
||||||
FindClose(dir->handle);
|
|
||||||
free(dir);
|
|
||||||
}
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
|
|
||||||
//get module handle of memptr
|
|
||||||
#ifdef linux
|
|
||||||
DLHANDLE DLLINTERNAL get_module_handle_of_memptr(void * memptr)
|
|
||||||
{
|
|
||||||
Dl_info dli;
|
|
||||||
memset(&dli, 0, sizeof(dli));
|
|
||||||
|
|
||||||
if(dladdr(memptr, &dli))
|
|
||||||
return(dlopen(dli.dli_fname, RTLD_NOW));
|
|
||||||
else
|
|
||||||
return((void*)0);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
DLHANDLE DLLINTERNAL get_module_handle_of_memptr(void * memptr)
|
|
||||||
{
|
|
||||||
MEMORY_BASIC_INFORMATION MBI;
|
|
||||||
|
|
||||||
if(!VirtualQuery(memptr, &MBI, sizeof(MBI)))
|
|
||||||
return(NULL);
|
|
||||||
if(MBI.State != MEM_COMMIT)
|
|
||||||
return(NULL);
|
|
||||||
if(!MBI.AllocationBase)
|
|
||||||
return(NULL);
|
|
||||||
|
|
||||||
return((DLHANDLE)MBI.AllocationBase);
|
|
||||||
}
|
|
||||||
#endif /* linux */
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// reg_support.cpp - support for things "registered" by plugins (console
|
|
||||||
// cmds, cvars, msgs, etc)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef linux
|
|
||||||
// enable extra routines in system header files, like strsignal
|
|
||||||
# ifndef _GNU_SOURCE
|
|
||||||
# define _GNU_SOURCE
|
|
||||||
# endif
|
|
||||||
#endif /* linux */
|
|
||||||
|
|
||||||
#include <string.h> // strsignal, etc
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
#include "sdk_util.h" // REG_SVR_COMMAND, etc
|
|
||||||
|
|
||||||
#include "reg_support.h" // me
|
|
||||||
#include "metamod.h" // RegCmds, g_Players, etc
|
|
||||||
#include "log_meta.h" // META_ERROR, etc
|
|
||||||
|
|
||||||
// "Register" support.
|
|
||||||
//
|
|
||||||
// This code is necessary to support the different "register" engine
|
|
||||||
// functions that can be called by plugins, so that the plugins can be
|
|
||||||
// safely unloaded without incurring segmentation faults.
|
|
||||||
//
|
|
||||||
// The problem was that, when a plugin called, say:
|
|
||||||
// REG_SVR_COMMAND("stub_version", svr_stub_version);
|
|
||||||
//
|
|
||||||
// the engine stored the address to the "stub_version" string, as well as,
|
|
||||||
// of course, the svr_stub_version() function pointer. If the plugin was
|
|
||||||
// unloaded, and dlclose()'d, the memory locations for both the string and
|
|
||||||
// function became invalid and unavailable. If the engine tried to
|
|
||||||
// strcmp() against the string, or tried to call the function pointer, it
|
|
||||||
// generated a segfault and killed the process.
|
|
||||||
//
|
|
||||||
// The solution used here is to create strings and functions allocated
|
|
||||||
// locally, in metamod.dll, which won't become unavailable or invalid due
|
|
||||||
// to a dlclose(). These local copies are passed to the engine instead of
|
|
||||||
// those allocated in the plugin DLLs. Thus, when a plugin is later
|
|
||||||
// unloaded and dlclose'd, the engine can still reference the memory
|
|
||||||
// locations of registered strings and functions, without segfaulting.
|
|
||||||
//
|
|
||||||
// Now, what happens with a registered string or function after a plugin is
|
|
||||||
// unloaded not quite as nice as I'd like.
|
|
||||||
//
|
|
||||||
// Console commands will print a message along the lines of:
|
|
||||||
// [metamod: command '%s' unavailable; plugin unloaded]
|
|
||||||
//
|
|
||||||
// Cvars though, have their value unaffected. This can be convenient when
|
|
||||||
// reloading a plugin, as the cvars keep their old values. However it can
|
|
||||||
// also be confusing, as there is no indication when viewing/setting cvars
|
|
||||||
// from the console that they no longer have an effect.
|
|
||||||
//
|
|
||||||
// Also note, the console commands for listing registered cmds and cvars
|
|
||||||
// will try to show the name of the associated plugin.
|
|
||||||
|
|
||||||
|
|
||||||
// Generic command handler, passed to the engine for any AddServerCommand
|
|
||||||
// calls made by the plugin. It finds the appropriate plugin function
|
|
||||||
// pointer to call based on CMD_ARGV(0).
|
|
||||||
void DLLHIDDEN meta_command_handler(void) {
|
|
||||||
MRegCmd *icmd;
|
|
||||||
const char *cmd;
|
|
||||||
|
|
||||||
META_DEBUG(5, ("called: meta_command_handler; arg0=%s args='%s'", CMD_ARGV(0), CMD_ARGS()));
|
|
||||||
cmd=CMD_ARGV(0);
|
|
||||||
if(!cmd) {
|
|
||||||
META_WARNING("Null command name in meta_command_handler() ??");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
icmd=RegCmds->find(cmd);
|
|
||||||
if(!icmd) {
|
|
||||||
META_WARNING("Couldn't find registered plugin command: %s", cmd);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(icmd->call() != mTRUE)
|
|
||||||
META_CONS("[metamod: command '%s' unavailable; plugin unloaded]", cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Replacement for engine routine AddServerCommand; called by plugins.
|
|
||||||
// Rather then handing the engine the plugin's command string and function
|
|
||||||
// pointer (both of which are allocated in the plugin DLL), this hands the
|
|
||||||
// engine a command string and function pointer allocated locally (in the
|
|
||||||
// metamod DLL).
|
|
||||||
//
|
|
||||||
// The string handed to the engine is just a strdup() of the plugin's
|
|
||||||
// string. The function pointer handed to the engine is actually a pointer
|
|
||||||
// to a generic command-handler function (see above).
|
|
||||||
void DLLHIDDEN meta_AddServerCommand(char *cmd_name, void (*function) (void)) {
|
|
||||||
MPlugin *iplug=NULL;
|
|
||||||
MRegCmd *icmd=NULL;
|
|
||||||
|
|
||||||
META_DEBUG(4, ("called: meta_AddServerCommand; cmd_name=%s, function=%d", cmd_name, function));
|
|
||||||
|
|
||||||
// try to find which plugin is registering this command
|
|
||||||
if(!(iplug=Plugins->find_memloc((void *)function))) {
|
|
||||||
// if this isn't supported on this OS, don't log an error
|
|
||||||
if(meta_errno != ME_OSNOTSUP)
|
|
||||||
META_WARNING("Failed to find memloc for regcmd '%s'", cmd_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if this command was previously registered, ie a "reloaded" plugin.
|
|
||||||
icmd=RegCmds->find(cmd_name);
|
|
||||||
if(!icmd) {
|
|
||||||
// If not found, add.
|
|
||||||
icmd=RegCmds->add(cmd_name);
|
|
||||||
if(!icmd) {
|
|
||||||
// error details logged in add()
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Only register if not previously registered..
|
|
||||||
REG_SVR_COMMAND(icmd->name, meta_command_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
icmd->pfnCmd=function;
|
|
||||||
icmd->status=RG_VALID;
|
|
||||||
// Store which plugin this is for, if we know. We can use '0' for
|
|
||||||
// unknown plugin, since plugin index starts at 1.
|
|
||||||
if(iplug)
|
|
||||||
icmd->plugid = iplug->index;
|
|
||||||
else
|
|
||||||
icmd->plugid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Replacement for engine routine CVarRegister; called by plugins. Rather
|
|
||||||
// then handing the engine the plugin's cvar structure (which is allocated
|
|
||||||
// in the plugin DLL), this hands the engine a cvar structure allocated
|
|
||||||
// locally (in the metamod DLL).
|
|
||||||
//
|
|
||||||
// The cvar handed to the engine is globally allocated in the metamod.dll;
|
|
||||||
// the "name" and "string" fields are strdup()'s of the plugin's strings.
|
|
||||||
// Note that, once this is done, the cvar_t allocated in the plugin is no
|
|
||||||
// longer used for _anything_. As long as everything sets/gets the cvar
|
|
||||||
// values via the engine functions, this will work fine. If the plugin
|
|
||||||
// code tries to _directly_ read/set the fields of its own cvar structures,
|
|
||||||
// it will fail to work properly.
|
|
||||||
void DLLHIDDEN meta_CVarRegister(cvar_t *pCvar) {
|
|
||||||
MPlugin *iplug=NULL;
|
|
||||||
MRegCvar *icvar=NULL;
|
|
||||||
|
|
||||||
META_DEBUG(4, ("called: meta_CVarRegister; name=%s", pCvar->name));
|
|
||||||
|
|
||||||
// try to find which plugin is registering this cvar
|
|
||||||
if(!(iplug=Plugins->find_memloc((void *)pCvar))) {
|
|
||||||
// if this isn't supported on this OS, don't log an error
|
|
||||||
if(meta_errno != ME_OSNOTSUP)
|
|
||||||
// Note: if cvar_t was malloc'd by the plugin, we can't
|
|
||||||
// determine the calling plugin. Thus, this becomes a Debug
|
|
||||||
// rather than Error message.
|
|
||||||
META_DEBUG(1, ("Failed to find memloc for regcvar '%s'",
|
|
||||||
pCvar->name));
|
|
||||||
}
|
|
||||||
|
|
||||||
// See if this cvar was previously registered, ie a "reloaded" plugin.
|
|
||||||
icvar=RegCvars->find(pCvar->name);
|
|
||||||
if(!icvar) {
|
|
||||||
// If not found, add.
|
|
||||||
icvar=RegCvars->add(pCvar->name);
|
|
||||||
if(!icvar) {
|
|
||||||
// error details logged in add()
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Reset to given value
|
|
||||||
icvar->set(pCvar);
|
|
||||||
CVAR_REGISTER(icvar->data);
|
|
||||||
}
|
|
||||||
// Note: if not a new cvar, then we don't set the values, and just keep
|
|
||||||
// the pre-existing value.
|
|
||||||
|
|
||||||
icvar->status=RG_VALID;
|
|
||||||
// Store which plugin this is for, if we know. Use '0' for unknown
|
|
||||||
// plugin, as plugin index starts at 1.
|
|
||||||
if(iplug)
|
|
||||||
icvar->plugid = iplug->index;
|
|
||||||
else
|
|
||||||
icvar->plugid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Replacement for engine routine RegUserMsg; called by plugins.
|
|
||||||
int DLLHIDDEN meta_RegUserMsg(const char *pszName, int iSize) {
|
|
||||||
return(REG_USER_MSG(strdup(pszName), iSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Intercept and record queries
|
|
||||||
void DLLHIDDEN meta_QueryClientCvarValue(const edict_t *player, const char *cvarName) {
|
|
||||||
g_Players.set_player_cvar_query(player, cvarName);
|
|
||||||
|
|
||||||
(*g_engfuncs.pfnQueryClientCvarValue)(player, cvarName);
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 ft=c :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2003 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
// see:
|
|
||||||
// http://msdn.microsoft.com/library/psdk/winui/rc_7x2d.htm
|
|
||||||
|
|
||||||
#include <winver.h>
|
|
||||||
#include "info_name.h"
|
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
|
||||||
FILEVERSION RC_VERS_DWORD
|
|
||||||
PRODUCTVERSION RC_VERS_DWORD
|
|
||||||
FILEFLAGSMASK 0x3fL
|
|
||||||
#ifdef _DEBUG
|
|
||||||
FILEFLAGS VS_FF_DEBUG
|
|
||||||
#else
|
|
||||||
FILEFLAGS 0x0L
|
|
||||||
#endif
|
|
||||||
FILEOS VOS__WINDOWS32
|
|
||||||
FILETYPE VFT_DLL
|
|
||||||
FILESUBTYPE VFT2_UNKNOWN
|
|
||||||
BEGIN
|
|
||||||
BLOCK "StringFileInfo"
|
|
||||||
BEGIN
|
|
||||||
BLOCK "040904b0"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Comments", RC_COMMENTS "\0"
|
|
||||||
VALUE "CompanyName", VAUTHOR "\0"
|
|
||||||
VALUE "FileDescription", RC_DESC "\0"
|
|
||||||
VALUE "FileVersion", VVERSION "\0"
|
|
||||||
VALUE "InternalName", RC_INTERNAL "\0"
|
|
||||||
VALUE "LegalCopyright", RC_COPYRIGHT "\0"
|
|
||||||
VALUE "License", RC_LICENSE "\0"
|
|
||||||
VALUE "OriginalFilename", RC_FILENAME "\0"
|
|
||||||
VALUE "PrivateBuild", "\0"
|
|
||||||
VALUE "ProductName", VNAME "\0"
|
|
||||||
VALUE "ProductVersion", VVERSION "\0"
|
|
||||||
VALUE "SpecialBuild", OPT_TYPE "\0"
|
|
||||||
END
|
|
||||||
END
|
|
||||||
BLOCK "VarFileInfo"
|
|
||||||
BEGIN
|
|
||||||
VALUE "Translation", 0x409, 1200
|
|
||||||
END
|
|
||||||
END
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// sdk_util.cpp - utility routines from HL SDK util.cpp
|
|
||||||
|
|
||||||
// Selected portions of dlls/util.cpp from SDK 2.1.
|
|
||||||
// Functions copied from there as needed...
|
|
||||||
// And modified to avoid buffer overflows (argh).
|
|
||||||
// Also modified to remove dependency on CBaseEntity class.
|
|
||||||
|
|
||||||
/***
|
|
||||||
*
|
|
||||||
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
|
|
||||||
*
|
|
||||||
* This product contains software technology licensed from Id
|
|
||||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
|
||||||
* All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use, distribution, and modification of this source code and/or resulting
|
|
||||||
* object code is restricted to non-commercial enhancements to products from
|
|
||||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
|
||||||
* without written permission from Valve LLC.
|
|
||||||
*
|
|
||||||
****/
|
|
||||||
/*
|
|
||||||
|
|
||||||
===== util.cpp ========================================================
|
|
||||||
|
|
||||||
Utility code. Really not optional after all.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <extdll.h>
|
|
||||||
#include "sdk_util.h"
|
|
||||||
|
|
||||||
#include <string.h> // for strncpy(), etc
|
|
||||||
|
|
||||||
#include "osdep.h" // win32 vsnprintf, etc
|
|
||||||
|
|
||||||
const char * DLLINTERNAL META_UTIL_VarArgs(const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list argptr;
|
|
||||||
static char string[4096];
|
|
||||||
|
|
||||||
va_start(argptr, format);
|
|
||||||
safevoid_vsnprintf(string, sizeof(string), format, argptr);
|
|
||||||
va_end(argptr);
|
|
||||||
|
|
||||||
return(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
short DLLINTERNAL FixedSigned16(float value, float scale)
|
|
||||||
{
|
|
||||||
int output;
|
|
||||||
|
|
||||||
output = (int)(value * scale);
|
|
||||||
|
|
||||||
if(output > 32767)
|
|
||||||
output = 32767;
|
|
||||||
|
|
||||||
if(output < -32768)
|
|
||||||
output = -32768;
|
|
||||||
|
|
||||||
return((short)output);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short DLLINTERNAL FixedUnsigned16(float value, float scale)
|
|
||||||
{
|
|
||||||
int output;
|
|
||||||
|
|
||||||
output = (int)(value * scale);
|
|
||||||
if(output < 0)
|
|
||||||
output = 0;
|
|
||||||
if(output > 0xFFFF)
|
|
||||||
output = 0xFFFF;
|
|
||||||
|
|
||||||
return((unsigned short)output);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void DLLINTERNAL META_UTIL_HudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const char *pMessage)
|
|
||||||
{
|
|
||||||
if(fast_FNullEnt(pEntity) || pEntity->free)
|
|
||||||
return;
|
|
||||||
|
|
||||||
MESSAGE_BEGIN( MSG_ONE, SVC_TEMPENTITY, NULL, pEntity );
|
|
||||||
WRITE_BYTE( TE_TEXTMESSAGE );
|
|
||||||
WRITE_BYTE( textparms.channel & 0xFF );
|
|
||||||
|
|
||||||
WRITE_SHORT( FixedSigned16( textparms.x, 1<<13 ) );
|
|
||||||
WRITE_SHORT( FixedSigned16( textparms.y, 1<<13 ) );
|
|
||||||
WRITE_BYTE( textparms.effect );
|
|
||||||
|
|
||||||
WRITE_BYTE( textparms.r1 );
|
|
||||||
WRITE_BYTE( textparms.g1 );
|
|
||||||
WRITE_BYTE( textparms.b1 );
|
|
||||||
WRITE_BYTE( textparms.a1 );
|
|
||||||
|
|
||||||
WRITE_BYTE( textparms.r2 );
|
|
||||||
WRITE_BYTE( textparms.g2 );
|
|
||||||
WRITE_BYTE( textparms.b2 );
|
|
||||||
WRITE_BYTE( textparms.a2 );
|
|
||||||
|
|
||||||
WRITE_SHORT( FixedUnsigned16( textparms.fadeinTime, 1<<8 ) );
|
|
||||||
WRITE_SHORT( FixedUnsigned16( textparms.fadeoutTime, 1<<8 ) );
|
|
||||||
WRITE_SHORT( FixedUnsigned16( textparms.holdTime, 1<<8 ) );
|
|
||||||
|
|
||||||
if(textparms.effect == 2)
|
|
||||||
WRITE_SHORT( FixedUnsigned16( textparms.fxTime, 1<<8 ) );
|
|
||||||
|
|
||||||
if(strlen( pMessage ) < 512)
|
|
||||||
{
|
|
||||||
WRITE_STRING( pMessage );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char tmp[512];
|
|
||||||
strncpy( tmp, pMessage, 511 );
|
|
||||||
tmp[511] = 0;
|
|
||||||
WRITE_STRING( tmp );
|
|
||||||
}
|
|
||||||
MESSAGE_END();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// studio.cpp - player model blending interfaces
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
//Jussi Kivilinna: This forwarder function to gamedll is not needed anymore, dynamic
|
|
||||||
// linkent code handles this too!
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// support_meta.cpp - generic support routines
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <extdll.h> // always
|
|
||||||
|
|
||||||
#include "metamod.h" // GameDLL
|
|
||||||
#include "support_meta.h" // me
|
|
||||||
#include "osdep.h" // sleep, etc
|
|
||||||
|
|
||||||
META_ERRNO meta_errno;
|
|
||||||
|
|
||||||
void DLLINTERNAL do_exit(int exitval) {
|
|
||||||
sleep(3);
|
|
||||||
exit(exitval);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks for a non-empty file, relative to the gamedir if necessary.
|
|
||||||
// Formerly used LOAD_FILE_FOR_ME, which provided a simple way to check for
|
|
||||||
// a file under the gamedir, but which would _also_ look in the sibling
|
|
||||||
// "valve" directory, thus sometimes finding files that weren't desired.
|
|
||||||
// Also, formerly named just "valid_file".
|
|
||||||
//
|
|
||||||
// Special-case-recognize "/dev/null" as a valid file.
|
|
||||||
int DLLINTERNAL valid_gamedir_file(const char *path) {
|
|
||||||
char buf[PATH_MAX];
|
|
||||||
struct stat st;
|
|
||||||
int ret, reg, size;
|
|
||||||
|
|
||||||
if(!path)
|
|
||||||
return(FALSE);
|
|
||||||
|
|
||||||
if(strmatch(path, "/dev/null"))
|
|
||||||
return(TRUE);
|
|
||||||
|
|
||||||
if(is_absolute_path(path))
|
|
||||||
STRNCPY(buf, path, sizeof(buf));
|
|
||||||
else
|
|
||||||
safevoid_snprintf(buf, sizeof(buf), "%s/%s", GameDLL.gamedir, path);
|
|
||||||
|
|
||||||
ret=stat(buf, &st);
|
|
||||||
if(ret != 0) {
|
|
||||||
META_DEBUG(5, ("Unable to stat '%s': %s", buf, strerror(errno)));
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
reg=S_ISREG(st.st_mode);
|
|
||||||
if(!reg) {
|
|
||||||
META_DEBUG(5, ("Not a regular file: %s", buf));
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
size=st.st_size;
|
|
||||||
if(!size) {
|
|
||||||
META_DEBUG(5, ("Empty file: %s", buf));
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ret==0 && reg && size)
|
|
||||||
return(TRUE);
|
|
||||||
else
|
|
||||||
return(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Turns path into a full path:
|
|
||||||
// - if not absolute, prepends gamedir
|
|
||||||
// - calls realpath() to collapse ".." and such
|
|
||||||
// - calls normalize_pathname() to fix backslashes, etc
|
|
||||||
//
|
|
||||||
// Much like realpath, buffer pointed to by fullpath is assumed to be
|
|
||||||
// able to store a string of PATH_MAX length.
|
|
||||||
char * DLLINTERNAL full_gamedir_path(const char *path, char *fullpath) {
|
|
||||||
char buf[PATH_MAX];
|
|
||||||
|
|
||||||
// Build pathname from filename, plus gamedir if relative path.
|
|
||||||
if(is_absolute_path(path))
|
|
||||||
STRNCPY(buf, path, sizeof(buf));
|
|
||||||
else
|
|
||||||
safevoid_snprintf(buf, sizeof(buf), "%s/%s", GameDLL.gamedir, path);
|
|
||||||
// Remove relative path components, if possible.
|
|
||||||
if(!realpath(buf, fullpath)) {
|
|
||||||
META_DEBUG(4, ("Unable to get realpath for '%s': %s", buf,
|
|
||||||
str_os_error()));
|
|
||||||
STRNCPY(fullpath, path, PATH_MAX);
|
|
||||||
}
|
|
||||||
// Replace backslashes, etc.
|
|
||||||
normalize_pathname(fullpath);
|
|
||||||
return(fullpath);
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
// vi: set ts=4 sw=4 :
|
|
||||||
// vim: set tw=75 :
|
|
||||||
|
|
||||||
// vdate.cpp - compile-time version date
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
|
||||||
*
|
|
||||||
* This file is part of Metamod.
|
|
||||||
*
|
|
||||||
* Metamod is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License as published by the
|
|
||||||
* Free Software Foundation; either version 2 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* Metamod is distributed in the hope that it will be useful, but
|
|
||||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Metamod; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*
|
|
||||||
* In addition, as a special exception, the author gives permission to
|
|
||||||
* link the code of this program with the Half-Life Game Engine ("HL
|
|
||||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
||||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
||||||
* respects for all of the code used other than the HL Engine and MODs
|
|
||||||
* from Valve. If you modify this file, you may extend this exception
|
|
||||||
* to your version of the file, but you are not obligated to do so. If
|
|
||||||
* you do not wish to do so, delete this exception statement from your
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "info_name.h" // for VNAME, VVERSION, etc
|
|
||||||
#include "vdate.h"
|
|
||||||
|
|
||||||
|
|
||||||
// Grab date/time of compile. The Makefile is set up to recompile this
|
|
||||||
// module before each link, so that this will always indicate the time the
|
|
||||||
// library was compiled and linked.
|
|
||||||
|
|
||||||
// This is in a separate file from vers_*, so it can be generically used by
|
|
||||||
// multiple projects.
|
|
||||||
|
|
||||||
char const *COMPILE_TIME=__DATE__ ", " __TIME__;
|
|
||||||
|
|
||||||
#ifndef COMPILE_TZ
|
|
||||||
#define COMPILE_TZ "EET"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char const *COMPILE_TZONE = COMPILE_TZ;
|
|
||||||
|
|
||||||
// Include a string for /usr/bin/ident.
|
|
||||||
|
|
||||||
char const *vstring="\n$Pg: " VNAME " -- " VVERSION " | " __DATE__ " - " __TIME__ " $\n";
|
|
||||||
Reference in New Issue
Block a user