First working compilation.

This commit is contained in:
Julian
2020-02-25 21:46:51 -03:00
parent 6cdc2ea18c
commit f2d8d91baf
88 changed files with 1959 additions and 13767 deletions

2
src/dlls/.gitignore vendored
View File

@@ -1,3 +1,5 @@
msgs/
opt.*/
debug.*/
*.o
*.so

View File

@@ -1,6 +1,9 @@
CPP = gcc
BASEFLAGS = -Dstricmp=strcasecmp -Dstrcmpi=strcasecmp
CPPFLAGS = ${BASEFLAGS} -m386 -O2 -w -I. -I../engine -I../common -I../pm_shared -I../../metamod
# COMPILE ONLY WITH GCC 4.8!
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 = \
agrunt.o \
@@ -42,7 +45,7 @@ OBJ = \
zombie.o
monster_mm_i386.so: ${OBJ}
${CPP} -fPIC -shared -o $@ ${OBJ}
${CPP} -m32 -fPIC -shared -o $@ ${OBJ}
clean:
-rm -f *.o

View File

@@ -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 )
{
studiohdr_t *pstudiohdr;
int i;
pstudiohdr = (studiohdr_t *)pmodel;
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);
// 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)
break;

View File

@@ -53,19 +53,19 @@ void CMApache :: Spawn( void )
if (pev->spawnflags & SF_WAITFORTRIGGER)
{
SetUse( StartupUse );
SetUse( &CMApache::StartupUse );
}
else
{
SetThink( HuntThink );
SetTouch( FlyTouch );
SetThink( &CMApache::HuntThink );
SetTouch( &CMApache::FlyTouch );
pev->nextthink = gpGlobals->time + 1.0;
}
m_iRockets = 10;
m_pBeam = NULL;
m_pGoalEnt = NULL;
m_pGoalEnt = NULL;
m_flGoalSpeed = 0.0f;
m_flForce = 0.0f;
@@ -122,8 +122,8 @@ void CMApache::NullThink( void )
void CMApache::StartupUse( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
{
SetThink( HuntThink );
SetTouch( FlyTouch );
SetThink( &CMApache::HuntThink );
SetTouch( &CMApache::FlyTouch );
pev->nextthink = gpGlobals->time + 0.1;
SetUse( NULL );
}
@@ -136,8 +136,8 @@ void CMApache :: Killed( entvars_t *pevAttacker, int iGib )
STOP_SOUND( ENT(pev), CHAN_STATIC, "apache/ap_rotor2.wav" );
UTIL_SetSize( pev, Vector( -32, -32, -64), Vector( 32, 32, 0) );
SetThink( DyingThink );
SetTouch( CrashTouch );
SetThink( &CMApache::DyingThink );
SetTouch( &CMApache::CrashTouch );
pev->nextthink = gpGlobals->time + 0.1;
pev->health = 0;
pev->takedamage = DAMAGE_NO;
@@ -346,7 +346,7 @@ jlb*/
WRITE_BYTE( BREAK_METAL );
MESSAGE_END();
SetThink( SUB_Remove );
SetThink( &CMApache::SUB_Remove );
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_SetOrigin( pev, pev->origin );
SetThink( IgniteThink );
SetTouch( ExplodeTouch );
SetThink( &CMApacheHVR::IgniteThink );
SetTouch( &CMApacheHVR::ExplodeTouch );
UTIL_MakeAimVectors( pev->angles );
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)
// set to accelerate
SetThink( AccelerateThink );
SetThink( &CMApacheHVR::AccelerateThink );
pev->nextthink = gpGlobals->time + 0.1;
}

View File

@@ -20,7 +20,7 @@
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "decals.h"
@@ -1141,7 +1141,7 @@ CMBMortar *CMBMortar::Shoot( edict_t *pOwner, Vector vecStart, Vector vecVelocit
pSpit->pev->velocity = vecVelocity;
pSpit->pev->owner = pOwner;
pSpit->pev->scale = 2.5;
pSpit->SetThink ( Animate );
pSpit->SetThink ( &CMBMortar::Animate );
pSpit->pev->nextthink = gpGlobals->time + 0.1;
}
return pSpit;

View File

@@ -19,7 +19,7 @@
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "nodes.h"
@@ -111,9 +111,9 @@ void CSquidSpit::Shoot( entvars_t *pevOwner, Vector vecStart, Vector vecVelocity
pSpit->pev->velocity = vecVelocity;
pSpit->pev->owner = ENT(pevOwner);
pSpit->SetThink ( Animate );
pSpit->SetThink ( &CSquidSpit::Animate );
pSpit->pev->nextthink = gpGlobals->time + 0.1;
pSpit->SetTouch ( SpitTouch );
pSpit->SetTouch ( &CSquidSpit::SpitTouch );
}
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;
}

View File

@@ -483,7 +483,7 @@ public:
BOOL FValidateHintType ( short sHint );
BOOL FCanActiveIdle ( void );
Schedule_t *GetScheduleOfType ( int Type );
Schedule_t *CMHoundeye :: GetSchedule( void );
Schedule_t *GetSchedule( void );
CUSTOM_SCHEDULES;

View File

@@ -113,7 +113,7 @@ void CMGib :: SpawnStickyGibs( entvars_t *pevVictim, Vector vecOrigin, int cGibs
pGib->pev->movetype = MOVETYPE_TOSS;
pGib->pev->solid = SOLID_BBOX;
UTIL_SetSize ( pGib->pev, Vector ( 0, 0 ,0 ), Vector ( 0, 0, 0 ) );
pGib->SetTouch ( StickyGibTouch );
pGib->SetTouch ( &CMGib::StickyGibTouch );
pGib->SetThink (NULL);
}
pGib->LimitVelocity();
@@ -327,7 +327,7 @@ void CMBaseMonster :: GibMonster( void )
if ( gibbed )
{
// don't remove players!
SetThink ( SUB_Remove );
SetThink ( &CMBaseMonster::SUB_Remove );
pev->nextthink = gpGlobals->time;
}
else
@@ -655,7 +655,7 @@ void CMBaseEntity :: SUB_StartFadeOut ( void )
pev->avelocity = g_vecZero;
pev->nextthink = gpGlobals->time + 0.1;
SetThink ( SUB_FadeOut );
SetThink ( &CMBaseEntity::SUB_FadeOut );
}
void CMBaseEntity :: SUB_FadeOut ( void )
@@ -669,7 +669,7 @@ void CMBaseEntity :: SUB_FadeOut ( void )
{
pev->renderamt = 0;
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 )
{
SetThink (SUB_StartFadeOut);
SetThink ( &CMGib::SUB_StartFadeOut );
pev->nextthink = gpGlobals->time + m_lifeTime;
}
else
@@ -740,7 +740,7 @@ void CMGib :: StickyGibTouch ( edict_t *pOther )
Vector vecSpot;
TraceResult tr;
SetThink ( SUB_Remove );
SetThink ( &CMGib::SUB_Remove );
pev->nextthink = gpGlobals->time + 5;
if (!FStrEq(STRING(pOther->v.classname), "worldspawn"))
@@ -781,8 +781,8 @@ void CMGib :: Spawn( const char *szGibModel )
pev->nextthink = gpGlobals->time + 4;
m_lifeTime = 10;
SetThink ( WaitTillLand );
SetTouch ( BounceGibTouch );
SetThink ( &CMGib::WaitTillLand );
SetTouch ( &CMGib::BounceGibTouch );
m_material = matNone;
m_cBloodDecals = 5;// how many blood decals this gib can place (1 per bounce until none remain).

View File

@@ -21,7 +21,7 @@
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "effects.h"
#include "schedule.h"
@@ -1104,8 +1104,8 @@ void CMControllerHeadBall :: Spawn( void )
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
UTIL_SetOrigin( pev, pev->origin );
SetThink( HuntThink );
SetTouch( BounceTouch );
SetThink( &CMControllerHeadBall::HuntThink );
SetTouch( &CMControllerHeadBall::BounceTouch );
m_vecIdeal = Vector( 0, 0, 0 );
@@ -1198,7 +1198,7 @@ void CMControllerHeadBall :: HuntThink( void )
m_flNextAttack = gpGlobals->time + 3.0;
SetThink( DieThink );
SetThink( &CMControllerHeadBall::DieThink );
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_SetOrigin( pev, pev->origin );
SetThink( AnimateThink );
SetTouch( ExplodeTouch );
SetThink( &CMControllerZapBall::AnimateThink );
SetTouch( &CMControllerZapBall::ExplodeTouch );
m_hOwner = pev->owner;
pev->dmgtime = gpGlobals->time; // keep track of when ball spawned

View File

@@ -18,7 +18,7 @@
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "defaultai.h"

File diff suppressed because it is too large Load Diff

View File

@@ -366,7 +366,7 @@ void CMSprite::Expand( float scaleSpeed, float fadeSpeed )
{
pev->speed = scaleSpeed;
pev->health = fadeSpeed;
SetThink( ExpandThink );
SetThink( &CMSprite::ExpandThink );
pev->nextthink = gpGlobals->time;
m_lastTime = gpGlobals->time;
@@ -421,7 +421,7 @@ void CMSprite::TurnOn( void )
pev->effects = 0;
if ( (pev->framerate && m_maxFrame > 1.0) || (pev->spawnflags & SF_SPRITE_ONCE) )
{
SetThink( AnimateThink );
SetThink( &CMSprite::AnimateThink );
pev->nextthink = gpGlobals->time;
m_lastTime = gpGlobals->time;
}

View File

@@ -79,7 +79,7 @@ public:
inline void AnimateAndDie( float framerate )
{
SetThink(AnimateUntilDead);
SetThink(&CMSprite::AnimateUntilDead);
pev->framerate = framerate;
pev->dmgtime = gpGlobals->time + (m_maxFrame / framerate);
pev->nextthink = gpGlobals->time;
@@ -165,7 +165,7 @@ public:
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 )
{
pev->dmg = damage;

View File

@@ -49,13 +49,7 @@ typedef int BOOL;
#define MAX_PATH PATH_MAX
#include <limits.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)
#endif
#endif //_WIN32
// Misc C-runtime library headers
@@ -63,6 +57,11 @@ typedef int BOOL;
#include "stdlib.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
typedef int func_t; //
typedef int string_t; // from engine's pr_comp.h;

View File

@@ -110,7 +110,7 @@ void CMGrenade::Explode( TraceResult *pTrace, int bitsDamageType )
}
pev->effects |= EF_NODRAW;
SetThink( Smoke );
SetThink( &CMGrenade::Smoke );
pev->velocity = g_vecZero;
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.
void CMGrenade::DetonateUse( edict_t *pActivator, edict_t *pCaller, USE_TYPE useType, float value )
{
SetThink( Detonate );
SetThink( &CMGrenade::Detonate );
pev->nextthink = gpGlobals->time;
}
void CMGrenade::PreDetonate( void )
{
SetThink( Detonate );
SetThink( &CMGrenade::Detonate );
pev->nextthink = gpGlobals->time + 1;
}
@@ -329,7 +329,7 @@ void CMGrenade :: TumbleThink( void )
if (pev->dmgtime <= gpGlobals->time)
{
SetThink( Detonate );
SetThink( &CMGrenade::Detonate );
}
if (pev->waterlevel != 0)
{
@@ -370,14 +370,14 @@ CMGrenade *CMGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector
pGrenade->pev->owner = ENT(pevOwner);
// make monsters afaid of it while in the air
pGrenade->SetThink( DangerSoundThink );
pGrenade->SetThink( &CMGrenade::DangerSoundThink );
pGrenade->pev->nextthink = gpGlobals->time;
// Tumble in air
pGrenade->pev->avelocity.x = RANDOM_FLOAT ( -100, -500 );
// Explode on contact
pGrenade->SetTouch( ExplodeTouch );
pGrenade->SetTouch( &CMGrenade::ExplodeTouch );
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->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
// 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().
pGrenade->pev->dmgtime = gpGlobals->time + time;
pGrenade->SetThink( TumbleThink );
pGrenade->SetThink( &CMGrenade::TumbleThink );
pGrenade->pev->nextthink = gpGlobals->time + 0.1;
if (time < 0.1)
{
@@ -452,9 +452,9 @@ CMGrenade * CMGrenade :: ShootSatchelCharge( entvars_t *pevOwner, Vector vecStar
pGrenade->pev->owner = ENT(pevOwner);
// Detonate in "time" seconds
pGrenade->SetThink( SUB_DoNothing );
pGrenade->SetUse( DetonateUse );
pGrenade->SetTouch( SlideTouch );
pGrenade->SetThink( &CMGrenade::SUB_DoNothing );
pGrenade->SetUse( &CMGrenade::DetonateUse );
pGrenade->SetTouch( &CMGrenade::SlideTouch );
pGrenade->pev->spawnflags = SF_DETONATE;
pGrenade->pev->friction = 0.9;

View File

@@ -21,7 +21,7 @@
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "weapons.h"

View File

@@ -19,7 +19,7 @@
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
@@ -349,7 +349,7 @@ void CMHeadCrab :: StartTask ( Task_t *pTask )
{
EMIT_SOUND_DYN( edict(), CHAN_WEAPON, pAttackSounds[0], GetSoundVolue(), ATTN_IDLE, 0, GetVoicePitch() );
m_IdealActivity = ACT_RANGE_ATTACK1;
SetTouch ( LeapTouch );
SetTouch ( &CMHeadCrab::LeapTouch );
break;
}
default:

View File

@@ -32,7 +32,7 @@
#include "plane.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "animation.h"

View File

@@ -19,7 +19,7 @@
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "weapons.h"
#include "hornet.h"
@@ -71,8 +71,8 @@ void CMHornet :: Spawn( void )
SET_MODEL(ENT( pev ), "models/hornet.mdl");
UTIL_SetSize( pev, Vector( -4, -4, -4 ), Vector( 4, 4, 4 ) );
SetTouch( DieTouch );
SetThink( StartTrack );
SetTouch( &CMHornet::DieTouch );
SetThink( &CMHornet::StartTrack );
edict_t *pSoundEnt = pev->owner;
if ( !pSoundEnt )
@@ -140,8 +140,8 @@ void CMHornet :: StartTrack ( void )
{
IgniteTrail();
SetTouch( TrackTouch );
SetThink( TrackTarget );
SetTouch( &CMHornet::TrackTouch );
SetThink( &CMHornet::TrackTarget );
pev->nextthink = gpGlobals->time + 0.1;
}
@@ -153,9 +153,9 @@ void CMHornet :: StartDart ( void )
{
IgniteTrail();
SetTouch( DartTouch );
SetTouch( &CMHornet::DartTouch );
SetThink( SUB_Remove );
SetThink( &CMHornet::SUB_Remove );
pev->nextthink = gpGlobals->time + 4;
}
@@ -228,7 +228,7 @@ void CMHornet :: TrackTarget ( void )
if (gpGlobals->time > m_flStopAttack)
{
SetTouch( NULL );
SetThink( SUB_Remove );
SetThink( &CMHornet::SUB_Remove );
pev->nextthink = gpGlobals->time + 0.1;
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->solid = SOLID_NOT;
SetThink ( SUB_Remove );
SetThink ( &CMHornet::SUB_Remove );
pev->nextthink = gpGlobals->time + 1;// stick around long enough for the sound to finish!
}

View File

@@ -19,7 +19,7 @@
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "animation.h"

View File

@@ -19,7 +19,7 @@
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "effects.h"

View File

@@ -90,13 +90,13 @@ bool scan_monster_cfg(FILE *fp)
{
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);
return TRUE; // error
}
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);
return TRUE; // error
}
@@ -109,13 +109,13 @@ bool scan_monster_cfg(FILE *fp)
{
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);
return TRUE; // error
}
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);
return TRUE; // error
}
@@ -126,19 +126,19 @@ bool scan_monster_cfg(FILE *fp)
{
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);
return TRUE; // error
}
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);
return TRUE; // error
}
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);
return TRUE; // error
}
@@ -150,19 +150,19 @@ bool scan_monster_cfg(FILE *fp)
{
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);
return TRUE; // error
}
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);
return TRUE; // error
}
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);
return TRUE; // error
}
@@ -173,19 +173,19 @@ bool scan_monster_cfg(FILE *fp)
{
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);
return TRUE; // error
}
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);
return TRUE; // error
}
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);
return TRUE; // error
}
@@ -211,7 +211,7 @@ bool scan_monster_cfg(FILE *fp)
}
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);
return TRUE;
}
@@ -220,7 +220,7 @@ bool scan_monster_cfg(FILE *fp)
}
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);
return TRUE; // error occurred
}
@@ -229,25 +229,25 @@ bool scan_monster_cfg(FILE *fp)
// check for all necessary fields here...
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!");
return TRUE;
}
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!");
return TRUE;
}
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!");
return TRUE;
}
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!");
return TRUE;
}
@@ -328,13 +328,13 @@ bool process_monster_cfg(void)
{
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);
}
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);
return TRUE; // return bad status
@@ -370,7 +370,7 @@ bool scan_monster_precache_cfg(FILE *fp)
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);
}
}
@@ -397,13 +397,13 @@ bool process_monster_precache_cfg(void)
{
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);
}
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);
return TRUE; // return bad status

View File

@@ -1629,9 +1629,9 @@ void CMBaseMonster :: MonsterInit ( void )
// set eye position
SetEyePosition();
SetThink( MonsterInitThink );
SetThink( &CMBaseMonster::MonsterInitThink );
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
// 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.
if ( !FStringNull(pev->targetname) )// wait until triggered
@@ -2770,7 +2770,7 @@ void CMBaseMonster :: MonsterInitDead( void )
// Setup health counters, etc.
BecomeDead();
SetThink( CorpseFallThink );
SetThink( &CMBaseMonster::CorpseFallThink );
pev->nextthink = gpGlobals->time + 0.5;
}

View File

@@ -19,12 +19,19 @@
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "nodes.h"
#include "animation.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 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.
//
for ( int i = 0; i < m_cNodes; i++)
int i;
for ( i = 0; i < m_cNodes; i++)
{
m_pNodes[ i ].m_flClosestSoFar = -1.0;
}
@@ -1411,12 +1419,12 @@ void CTestHull :: Spawn( entvars_t *pevMasterNode )
if ( WorldGraph.m_fGraphPresent )
{// graph loaded from disk, so we don't need the test hull
SetThink ( SUB_Remove );
SetThink ( &CTestHull::SUB_Remove );
pev->nextthink = gpGlobals->time;
}
else
{
SetThink ( DropDelay );
SetThink ( &CTestHull::DropDelay );
pev->nextthink = gpGlobals->time + 1;
}
@@ -1436,7 +1444,7 @@ void CTestHull::DropDelay ( void )
UTIL_SetOrigin ( VARS(pev), WorldGraph.m_pNodes[ 0 ].m_vecOrigin );
SetThink ( CallBuildNodeGraph );
SetThink ( &CTestHull::CallBuildNodeGraph );
pev->nextthink = gpGlobals->time + 1;
}
@@ -1584,7 +1592,7 @@ void CTestHull :: BuildNodeGraph( void )
float flDist;
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;
// 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" );
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->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
// 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
// number given by iZone.
@@ -2742,8 +2752,9 @@ void CGraph::SortNodes(void)
// things and patchup the links.
//
int iNodeCnt = 0;
int i;
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;
}
@@ -2808,7 +2819,8 @@ void CGraph::BuildLinkLookups(void)
ALERT(at_aiconsole, "Couldn't allocated Link Lookup Table.\n");
return;
}
for (int i = 0; i < m_nHashLinks; i++)
int i;
for (i = 0; i < m_nHashLinks; i++)
{
m_pHashLinks[i] = ENTRY_STATE_EMPTY;
}
@@ -2848,7 +2860,8 @@ void CGraph::BuildRegionTables(void)
// 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_RegionMax[i] = -999999999.0; // just a big number out there;
@@ -2875,10 +2888,11 @@ void CGraph::BuildRegionTables(void)
m_pNodes[i].m_Region[1] = CALC_RANGE(m_pNodes[i].m_vecOrigin.y, m_RegionMin[1], m_RegionMax[1]);
m_pNodes[i].m_Region[2] = CALC_RANGE(m_pNodes[i].m_vecOrigin.z, m_RegionMin[2], m_RegionMax[2]);
}
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_RangeEnd[i][j] = 0;
@@ -3012,7 +3026,8 @@ void CGraph :: ComputeStaticRoutingTables( void )
// 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++)
{
@@ -3228,7 +3243,8 @@ void CGraph :: ComputeStaticRoutingTables( void )
int nRoute = p - pRoute;
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)
{
@@ -3320,7 +3336,8 @@ void CGraph :: TestRoutingTables( void )
//
#if 1
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]
//

View File

@@ -19,7 +19,7 @@
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "defaultai.h"

View File

@@ -114,7 +114,7 @@ void scan_monster_skill(FILE *fp)
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);
}
}
@@ -231,13 +231,13 @@ void monster_skill_init(void)
{
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);
}
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);
}
@@ -247,7 +247,7 @@ void monster_skill_init(void)
}
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);
}
}

View File

@@ -24,6 +24,9 @@
#include "cmtalkmonster.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 );

View File

@@ -61,8 +61,8 @@ void CMSqueakGrenade :: Spawn( void )
UTIL_SetSize(pev, Vector( -4, -4, 0), Vector(4, 4, 8));
UTIL_SetOrigin( pev, pev->origin );
SetTouch( SuperBounceTouch );
SetThink( HuntThink );
SetTouch( &CMSqueakGrenade::SuperBounceTouch );
SetThink( &CMSqueakGrenade::HuntThink );
pev->nextthink = gpGlobals->time + 0.1;
m_flNextHunt = gpGlobals->time + 1E6;
@@ -102,7 +102,7 @@ void CMSqueakGrenade::Precache( void )
void CMSqueakGrenade :: Killed( entvars_t *pevAttacker, int iGib )
{
pev->model = iStringNull;// make invisible
SetThink( SUB_Remove );
SetThink( &CMSqueakGrenade::SUB_Remove );
SetTouch( NULL );
pev->nextthink = gpGlobals->time + 0.1;

View File

@@ -177,7 +177,7 @@ void CMBaseDelay :: SUB_UseTargets( edict_t *pActivator, USE_TYPE useType, float
pTemp->pev->nextthink = gpGlobals->time + m_flDelay;
pTemp->SetThink( DelayThink );
pTemp->SetThink( &CMBaseDelay::DelayThink );
// Save the 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
pev->nextthink = pev->ltime + flTravelTime;
SetThink( LinearMoveDone );
SetThink( &CMBaseToggle::LinearMoveDone );
// scale the destdelta vector by the time spent traveling to get velocity
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
pev->nextthink = pev->ltime + flTravelTime;
SetThink( AngularMoveDone );
SetThink( &CMBaseToggle::AngularMoveDone );
// scale the destdelta vector by the time spent traveling to get velocity
pev->avelocity = vecDestDelta / flTravelTime;

View File

@@ -15,7 +15,7 @@
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"
#include "cmtalkmonster.h"

View File

@@ -178,6 +178,7 @@ typedef enum
} TOGGLE_STATE;
// Misc useful
#include "string.h"
inline BOOL FStrEq(const char*sz1, const char*sz2)
{ return (strcmp(sz1, sz2) == 0); }
inline BOOL FClassnameIs(edict_t* pent, const char* szClassname)

View File

@@ -21,7 +21,7 @@
#include "extdll.h"
#include "util.h"
#include "cmbase.h"
#include "cmbasemonster.h"
#include "cmbasemonster.h"
#include "monsters.h"
#include "schedule.h"

201
src/engine/Sequence.h Normal file
View 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
View 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
View 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
View 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

View File

@@ -17,7 +17,9 @@
#ifndef CUSTOM_H
#define CUSTOM_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#include "const.h"

View File

@@ -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
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.

View File

@@ -1,7 +1,9 @@
#if !defined EDICT_H
#define EDICT_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
#define MAX_ENT_LEAFS 48

View File

@@ -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
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
@@ -15,6 +15,8 @@
#ifndef EIFACE_H
#define EIFACE_H
#include "archtypes.h" // DAL
#ifdef HLDEMO_BUILD
#define INTERFACE_VERSION 001
#else // !HLDEMO_BUILD, i.e., regular version of HL
@@ -24,6 +26,7 @@
#include <stdio.h>
#include "custom.h"
#include "cvardef.h"
#include "Sequence.h"
//
// Defines entity interface between engine and DLLs.
// This header file included by engine files and DLL files.
@@ -60,9 +63,10 @@ typedef enum
// For integrity checking of content on clients
typedef enum
{
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_specifybounds, // For model files only, the geometry must fit in the specified bbox
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_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;
// Returned by TraceLine
@@ -96,6 +100,7 @@ typedef struct
#include "../common/crc.h"
// Engine hands this to DLLs for functionality callbacks
typedef struct enginefuncs_s
{
@@ -161,8 +166,13 @@ typedef struct enginefuncs_s
void (*pfnCVarSetFloat) (const char *szVarName, float flValue);
void (*pfnCVarSetString) (const char *szVarName, const char *szValue);
void (*pfnAlertMessage) (ALERT_TYPE atype, char *szFmt, ...);
#ifdef HLSDK_3_2_OLD_EIFACE
void (*pfnEngineFprintf) (FILE *pfile, char *szFmt, ...);
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 (*pfnFreeEntPrivateData) (edict_t *pEdict);
const char* (*pfnSzFromIndex) (int iString);
@@ -177,8 +187,13 @@ typedef struct enginefuncs_s
int (*pfnRegUserMsg) (const char *pszName, int iSize);
void (*pfnAnimationAutomove) (const edict_t* pEdict, float flTime);
void (*pfnGetBonePosition) (const edict_t* pEdict, int iBone, float *rgflOrigin, float *rgflAngles );
#ifdef HLSDK_3_2_OLD_EIFACE
unsigned long (*pfnFunctionFromName) ( const char *pName );
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 (*pfnServerPrint) ( const char *szMsg );
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_ProcessByte) (CRC32_t *pulCRC, unsigned char ch);
CRC32_t (*pfnCRC32_Final) (CRC32_t pulCRC);
#ifdef HLSDK_3_2_OLD_EIFACE
long (*pfnRandomLong) (long lLow, long lHigh);
#else
int32 (*pfnRandomLong) (int32 lLow, int32 lHigh);
#endif
float (*pfnRandomFloat) (float flLow, float flHigh);
void (*pfnSetView) (const edict_t *pClient, const edict_t *pViewent );
float (*pfnTime) ( void );
@@ -259,9 +278,49 @@ typedef struct enginefuncs_s
qboolean (*pfnVoice_GetClientListening)(int iReceiver, int iSender);
qboolean (*pfnVoice_SetClientListening)(int iReceiver, int iSender, qboolean bListen);
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;
// ONLY ADD NEW FUNCTIONS TO THE END OF THIS STRUCT. INTERFACE VERSION IS FROZEN AT 138
// Passed to pfnKeyValue
@@ -270,7 +329,11 @@ typedef struct KeyValueData_s
char *szClassName; // in: entity classname
char *szKeyName; // in: name 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
#else
int32 fHandled; // out: DLL sets to true if key-value pair was understood
#endif
} KeyValueData;
@@ -357,9 +420,11 @@ typedef enum _fieldtypes
FIELD_TYPECOUNT, // MUST BE LAST
} FIELDTYPE;
#ifndef linux
#ifndef offsetof
#define offsetof(s,m) (size_t)&(((s *)0)->m)
#endif
#endif
#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)
@@ -380,7 +445,16 @@ typedef struct
short flags;
} 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
{
@@ -481,6 +555,14 @@ typedef struct
void (*pfnOnFreeEntPrivateData)(edict_t *pEnt);
void (*pfnGameShutdown)(void);
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;
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 (*APIFUNCTION2)( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
#endif EIFACE_H
#endif /* EIFACE_H */

131
src/engine/keydefs.h Normal file
View 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

View File

@@ -15,7 +15,9 @@
#ifndef PROGDEFS_H
#define PROGDEFS_H
#ifdef _WIN32
#ifndef __MINGW32__
#pragma once
#endif /* not __MINGW32__ */
#endif
typedef struct
@@ -221,4 +223,4 @@ typedef struct entvars_s
} entvars_t;
#endif // PROGDEFS_H
#endif // PROGDEFS_H

82
src/engine/progs.h Normal file
View 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

View File

@@ -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
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.

View File

@@ -1,3 +0,0 @@
msgs/
opt.*/
debug.*/

View File

@@ -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

View File

@@ -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

View File

@@ -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) );

View File

@@ -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 },
};

View File

@@ -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

View File

@@ -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");
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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

View File

@@ -37,6 +37,7 @@
#ifndef ENGINE_API_H
#define ENGINE_API_H
#include <stdint.h> // why?
#include "comp_dep.h"
// 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);
#else
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
typedef void * (*FN_PVENTPRIVATEDATA) (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 const char * (*FN_NAMEFORFUNCTION) ( unsigned long function );
#else
typedef uint32 (*FN_FUNCTIONFROMNAME) ( const char *pName );
typedef const char * (*FN_NAMEFORFUNCTION) ( uint32 function );
typedef uint32_t (*FN_FUNCTIONFROMNAME) ( const char *pName );
typedef const char * (*FN_NAMEFORFUNCTION) ( uint32_t function );
#endif
typedef void (*FN_CLIENTPRINTF) ( edict_t *pEdict, PRINT_TYPE ptype, 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
typedef long (*FN_RANDOMLONG) (long lLow, long lHigh);
#else
typedef int32 (*FN_RANDOMLONG) (int32 lLow, int32 lHigh);
typedef int32_t (*FN_RANDOMLONG) (int32_t lLow, int32_t lHigh);
#endif
typedef float (*FN_RANDOMFLOAT) (float flLow, float flHigh);
typedef void (*FN_SETVIEW) (const edict_t *pClient, const edict_t *pViewent );

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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)
}
}

View File

@@ -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

View File

@@ -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");

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -1,5 +0,0 @@
LIBRARY metamod
EXPORTS
GiveFnptrsToDll @1
SECTIONS
.data READ WRITE

View File

@@ -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

View File

@@ -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>

View File

View File

@@ -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);
}

View File

@@ -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

View File

View File

@@ -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);
}

View File

@@ -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
};

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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));
}

View File

@@ -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 */

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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!

View File

@@ -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);
}

View File

@@ -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";