First working compilation.
This commit is contained in:
2
src/dlls/.gitignore
vendored
2
src/dlls/.gitignore
vendored
@@ -1,3 +1,5 @@
|
||||
msgs/
|
||||
opt.*/
|
||||
debug.*/
|
||||
*.o
|
||||
*.so
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
1540
src/dlls/dllapi.cpp
1540
src/dlls/dllapi.cpp
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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!
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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]
|
||||
//
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
201
src/engine/Sequence.h
Normal file
@@ -0,0 +1,201 @@
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// S c r i p t e d S e q u e n c e s
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#ifndef _INCLUDE_SEQUENCE_H_
|
||||
#define _INCLUDE_SEQUENCE_H_
|
||||
|
||||
|
||||
#ifndef _DEF_BYTE_
|
||||
typedef unsigned char byte;
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// client_textmessage_t
|
||||
//---------------------------------------------------------------------------
|
||||
typedef struct client_textmessage_s
|
||||
{
|
||||
int effect;
|
||||
byte r1, g1, b1, a1; // 2 colors for effects
|
||||
byte r2, g2, b2, a2;
|
||||
float x;
|
||||
float y;
|
||||
float fadein;
|
||||
float fadeout;
|
||||
float holdtime;
|
||||
float fxtime;
|
||||
const char *pName;
|
||||
const char *pMessage;
|
||||
} client_textmessage_t;
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// sequenceDefaultBits_e
|
||||
//
|
||||
// Enumerated list of possible modifiers for a command. This enumeration
|
||||
// is used in a bitarray controlling what modifiers are specified for a command.
|
||||
//---------------------------------------------------------------------------
|
||||
enum sequenceModifierBits
|
||||
{
|
||||
SEQUENCE_MODIFIER_EFFECT_BIT = (1 << 1),
|
||||
SEQUENCE_MODIFIER_POSITION_BIT = (1 << 2),
|
||||
SEQUENCE_MODIFIER_COLOR_BIT = (1 << 3),
|
||||
SEQUENCE_MODIFIER_COLOR2_BIT = (1 << 4),
|
||||
SEQUENCE_MODIFIER_FADEIN_BIT = (1 << 5),
|
||||
SEQUENCE_MODIFIER_FADEOUT_BIT = (1 << 6),
|
||||
SEQUENCE_MODIFIER_HOLDTIME_BIT = (1 << 7),
|
||||
SEQUENCE_MODIFIER_FXTIME_BIT = (1 << 8),
|
||||
SEQUENCE_MODIFIER_SPEAKER_BIT = (1 << 9),
|
||||
SEQUENCE_MODIFIER_LISTENER_BIT = (1 << 10),
|
||||
SEQUENCE_MODIFIER_TEXTCHANNEL_BIT = (1 << 11),
|
||||
};
|
||||
typedef enum sequenceModifierBits sequenceModifierBits_e ;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// sequenceCommandEnum_e
|
||||
//
|
||||
// Enumerated sequence command types.
|
||||
//---------------------------------------------------------------------------
|
||||
enum sequenceCommandEnum_
|
||||
{
|
||||
SEQUENCE_COMMAND_ERROR = -1,
|
||||
SEQUENCE_COMMAND_PAUSE = 0,
|
||||
SEQUENCE_COMMAND_FIRETARGETS,
|
||||
SEQUENCE_COMMAND_KILLTARGETS,
|
||||
SEQUENCE_COMMAND_TEXT,
|
||||
SEQUENCE_COMMAND_SOUND,
|
||||
SEQUENCE_COMMAND_GOSUB,
|
||||
SEQUENCE_COMMAND_SENTENCE,
|
||||
SEQUENCE_COMMAND_REPEAT,
|
||||
SEQUENCE_COMMAND_SETDEFAULTS,
|
||||
SEQUENCE_COMMAND_MODIFIER,
|
||||
SEQUENCE_COMMAND_POSTMODIFIER,
|
||||
SEQUENCE_COMMAND_NOOP,
|
||||
|
||||
SEQUENCE_MODIFIER_EFFECT,
|
||||
SEQUENCE_MODIFIER_POSITION,
|
||||
SEQUENCE_MODIFIER_COLOR,
|
||||
SEQUENCE_MODIFIER_COLOR2,
|
||||
SEQUENCE_MODIFIER_FADEIN,
|
||||
SEQUENCE_MODIFIER_FADEOUT,
|
||||
SEQUENCE_MODIFIER_HOLDTIME,
|
||||
SEQUENCE_MODIFIER_FXTIME,
|
||||
SEQUENCE_MODIFIER_SPEAKER,
|
||||
SEQUENCE_MODIFIER_LISTENER,
|
||||
SEQUENCE_MODIFIER_TEXTCHANNEL,
|
||||
};
|
||||
typedef enum sequenceCommandEnum_ sequenceCommandEnum_e;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// sequenceCommandType_e
|
||||
//
|
||||
// Typeerated sequence command types.
|
||||
//---------------------------------------------------------------------------
|
||||
enum sequenceCommandType_
|
||||
{
|
||||
SEQUENCE_TYPE_COMMAND,
|
||||
SEQUENCE_TYPE_MODIFIER,
|
||||
};
|
||||
typedef enum sequenceCommandType_ sequenceCommandType_e;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// sequenceCommandMapping_s
|
||||
//
|
||||
// A mapping of a command enumerated-value to its name.
|
||||
//---------------------------------------------------------------------------
|
||||
typedef struct sequenceCommandMapping_ sequenceCommandMapping_s;
|
||||
struct sequenceCommandMapping_
|
||||
{
|
||||
sequenceCommandEnum_e commandEnum;
|
||||
const char* commandName;
|
||||
sequenceCommandType_e commandType;
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// sequenceCommandLine_s
|
||||
//
|
||||
// Structure representing a single command (usually 1 line) from a
|
||||
// .SEQ file entry.
|
||||
//---------------------------------------------------------------------------
|
||||
typedef struct sequenceCommandLine_ sequenceCommandLine_s;
|
||||
struct sequenceCommandLine_
|
||||
{
|
||||
int commandType; // Specifies the type of command
|
||||
client_textmessage_t clientMessage; // Text HUD message struct
|
||||
char* speakerName; // Targetname of speaking entity
|
||||
char* listenerName; // Targetname of entity being spoken to
|
||||
char* soundFileName; // Name of sound file to play
|
||||
char* sentenceName; // Name of sentences.txt to play
|
||||
char* fireTargetNames; // List of targetnames to fire
|
||||
char* killTargetNames; // List of targetnames to remove
|
||||
float delay; // Seconds 'till next command
|
||||
int repeatCount; // If nonzero, reset execution pointer to top of block (N times, -1 = infinite)
|
||||
int textChannel; // Display channel on which text message is sent
|
||||
int modifierBitField; // Bit field to specify what clientmessage fields are valid
|
||||
sequenceCommandLine_s* nextCommandLine; // Next command (linked list)
|
||||
};
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// sequenceEntry_s
|
||||
//
|
||||
// Structure representing a single command (usually 1 line) from a
|
||||
// .SEQ file entry.
|
||||
//---------------------------------------------------------------------------
|
||||
typedef struct sequenceEntry_ sequenceEntry_s;
|
||||
struct sequenceEntry_
|
||||
{
|
||||
char* fileName; // Name of sequence file without .SEQ extension
|
||||
char* entryName; // Name of entry label in file
|
||||
sequenceCommandLine_s* firstCommand; // Linked list of commands in entry
|
||||
sequenceEntry_s* nextEntry; // Next loaded entry
|
||||
qboolean isGlobal; // Is entry retained over level transitions?
|
||||
};
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// sentenceEntry_s
|
||||
// Structure representing a single sentence of a group from a .SEQ
|
||||
// file entry. Sentences are identical to entries in sentences.txt, but
|
||||
// can be unique per level and are loaded/unloaded with the level.
|
||||
//---------------------------------------------------------------------------
|
||||
typedef struct sentenceEntry_ sentenceEntry_s;
|
||||
struct sentenceEntry_
|
||||
{
|
||||
char* data; // sentence data (ie "We have hostiles" )
|
||||
sentenceEntry_s* nextEntry; // Next loaded entry
|
||||
qboolean isGlobal; // Is entry retained over level transitions?
|
||||
unsigned int index; // this entry's position in the file.
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// sentenceGroupEntry_s
|
||||
// Structure representing a group of sentences found in a .SEQ file.
|
||||
// A sentence group is defined by all sentences with the same name, ignoring
|
||||
// the number at the end of the sentence name. Groups enable a sentence
|
||||
// to be picked at random across a group.
|
||||
//--------------------------------------------------------------------------
|
||||
typedef struct sentenceGroupEntry_ sentenceGroupEntry_s;
|
||||
struct sentenceGroupEntry_
|
||||
{
|
||||
char* groupName; // name of the group (ie CT_ALERT )
|
||||
unsigned int numSentences; // number of sentences in group
|
||||
sentenceEntry_s* firstSentence; // head of linked list of sentences in group
|
||||
sentenceGroupEntry_s* nextEntry; // next loaded group
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function declarations
|
||||
//---------------------------------------------------------------------------
|
||||
sequenceEntry_s* SequenceGet( const char* fileName, const char* entryName );
|
||||
void Sequence_ParseFile( const char* fileName, qboolean isGlobal );
|
||||
void Sequence_OnLevelLoad( const char* mapName );
|
||||
sentenceEntry_s* SequencePickSentence( const char *groupName, int pickMethod, int *picked );
|
||||
|
||||
#endif /* _INCLUDE_SEQUENCE_H_ */
|
||||
177
src/engine/anorms.h
Normal file
177
src/engine/anorms.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
|
||||
{-0.525731, 0.000000, 0.850651},
|
||||
{-0.442863, 0.238856, 0.864188},
|
||||
{-0.295242, 0.000000, 0.955423},
|
||||
{-0.309017, 0.500000, 0.809017},
|
||||
{-0.162460, 0.262866, 0.951056},
|
||||
{0.000000, 0.000000, 1.000000},
|
||||
{0.000000, 0.850651, 0.525731},
|
||||
{-0.147621, 0.716567, 0.681718},
|
||||
{0.147621, 0.716567, 0.681718},
|
||||
{0.000000, 0.525731, 0.850651},
|
||||
{0.309017, 0.500000, 0.809017},
|
||||
{0.525731, 0.000000, 0.850651},
|
||||
{0.295242, 0.000000, 0.955423},
|
||||
{0.442863, 0.238856, 0.864188},
|
||||
{0.162460, 0.262866, 0.951056},
|
||||
{-0.681718, 0.147621, 0.716567},
|
||||
{-0.809017, 0.309017, 0.500000},
|
||||
{-0.587785, 0.425325, 0.688191},
|
||||
{-0.850651, 0.525731, 0.000000},
|
||||
{-0.864188, 0.442863, 0.238856},
|
||||
{-0.716567, 0.681718, 0.147621},
|
||||
{-0.688191, 0.587785, 0.425325},
|
||||
{-0.500000, 0.809017, 0.309017},
|
||||
{-0.238856, 0.864188, 0.442863},
|
||||
{-0.425325, 0.688191, 0.587785},
|
||||
{-0.716567, 0.681718, -0.147621},
|
||||
{-0.500000, 0.809017, -0.309017},
|
||||
{-0.525731, 0.850651, 0.000000},
|
||||
{0.000000, 0.850651, -0.525731},
|
||||
{-0.238856, 0.864188, -0.442863},
|
||||
{0.000000, 0.955423, -0.295242},
|
||||
{-0.262866, 0.951056, -0.162460},
|
||||
{0.000000, 1.000000, 0.000000},
|
||||
{0.000000, 0.955423, 0.295242},
|
||||
{-0.262866, 0.951056, 0.162460},
|
||||
{0.238856, 0.864188, 0.442863},
|
||||
{0.262866, 0.951056, 0.162460},
|
||||
{0.500000, 0.809017, 0.309017},
|
||||
{0.238856, 0.864188, -0.442863},
|
||||
{0.262866, 0.951056, -0.162460},
|
||||
{0.500000, 0.809017, -0.309017},
|
||||
{0.850651, 0.525731, 0.000000},
|
||||
{0.716567, 0.681718, 0.147621},
|
||||
{0.716567, 0.681718, -0.147621},
|
||||
{0.525731, 0.850651, 0.000000},
|
||||
{0.425325, 0.688191, 0.587785},
|
||||
{0.864188, 0.442863, 0.238856},
|
||||
{0.688191, 0.587785, 0.425325},
|
||||
{0.809017, 0.309017, 0.500000},
|
||||
{0.681718, 0.147621, 0.716567},
|
||||
{0.587785, 0.425325, 0.688191},
|
||||
{0.955423, 0.295242, 0.000000},
|
||||
{1.000000, 0.000000, 0.000000},
|
||||
{0.951056, 0.162460, 0.262866},
|
||||
{0.850651, -0.525731, 0.000000},
|
||||
{0.955423, -0.295242, 0.000000},
|
||||
{0.864188, -0.442863, 0.238856},
|
||||
{0.951056, -0.162460, 0.262866},
|
||||
{0.809017, -0.309017, 0.500000},
|
||||
{0.681718, -0.147621, 0.716567},
|
||||
{0.850651, 0.000000, 0.525731},
|
||||
{0.864188, 0.442863, -0.238856},
|
||||
{0.809017, 0.309017, -0.500000},
|
||||
{0.951056, 0.162460, -0.262866},
|
||||
{0.525731, 0.000000, -0.850651},
|
||||
{0.681718, 0.147621, -0.716567},
|
||||
{0.681718, -0.147621, -0.716567},
|
||||
{0.850651, 0.000000, -0.525731},
|
||||
{0.809017, -0.309017, -0.500000},
|
||||
{0.864188, -0.442863, -0.238856},
|
||||
{0.951056, -0.162460, -0.262866},
|
||||
{0.147621, 0.716567, -0.681718},
|
||||
{0.309017, 0.500000, -0.809017},
|
||||
{0.425325, 0.688191, -0.587785},
|
||||
{0.442863, 0.238856, -0.864188},
|
||||
{0.587785, 0.425325, -0.688191},
|
||||
{0.688191, 0.587785, -0.425325},
|
||||
{-0.147621, 0.716567, -0.681718},
|
||||
{-0.309017, 0.500000, -0.809017},
|
||||
{0.000000, 0.525731, -0.850651},
|
||||
{-0.525731, 0.000000, -0.850651},
|
||||
{-0.442863, 0.238856, -0.864188},
|
||||
{-0.295242, 0.000000, -0.955423},
|
||||
{-0.162460, 0.262866, -0.951056},
|
||||
{0.000000, 0.000000, -1.000000},
|
||||
{0.295242, 0.000000, -0.955423},
|
||||
{0.162460, 0.262866, -0.951056},
|
||||
{-0.442863, -0.238856, -0.864188},
|
||||
{-0.309017, -0.500000, -0.809017},
|
||||
{-0.162460, -0.262866, -0.951056},
|
||||
{0.000000, -0.850651, -0.525731},
|
||||
{-0.147621, -0.716567, -0.681718},
|
||||
{0.147621, -0.716567, -0.681718},
|
||||
{0.000000, -0.525731, -0.850651},
|
||||
{0.309017, -0.500000, -0.809017},
|
||||
{0.442863, -0.238856, -0.864188},
|
||||
{0.162460, -0.262866, -0.951056},
|
||||
{0.238856, -0.864188, -0.442863},
|
||||
{0.500000, -0.809017, -0.309017},
|
||||
{0.425325, -0.688191, -0.587785},
|
||||
{0.716567, -0.681718, -0.147621},
|
||||
{0.688191, -0.587785, -0.425325},
|
||||
{0.587785, -0.425325, -0.688191},
|
||||
{0.000000, -0.955423, -0.295242},
|
||||
{0.000000, -1.000000, 0.000000},
|
||||
{0.262866, -0.951056, -0.162460},
|
||||
{0.000000, -0.850651, 0.525731},
|
||||
{0.000000, -0.955423, 0.295242},
|
||||
{0.238856, -0.864188, 0.442863},
|
||||
{0.262866, -0.951056, 0.162460},
|
||||
{0.500000, -0.809017, 0.309017},
|
||||
{0.716567, -0.681718, 0.147621},
|
||||
{0.525731, -0.850651, 0.000000},
|
||||
{-0.238856, -0.864188, -0.442863},
|
||||
{-0.500000, -0.809017, -0.309017},
|
||||
{-0.262866, -0.951056, -0.162460},
|
||||
{-0.850651, -0.525731, 0.000000},
|
||||
{-0.716567, -0.681718, -0.147621},
|
||||
{-0.716567, -0.681718, 0.147621},
|
||||
{-0.525731, -0.850651, 0.000000},
|
||||
{-0.500000, -0.809017, 0.309017},
|
||||
{-0.238856, -0.864188, 0.442863},
|
||||
{-0.262866, -0.951056, 0.162460},
|
||||
{-0.864188, -0.442863, 0.238856},
|
||||
{-0.809017, -0.309017, 0.500000},
|
||||
{-0.688191, -0.587785, 0.425325},
|
||||
{-0.681718, -0.147621, 0.716567},
|
||||
{-0.442863, -0.238856, 0.864188},
|
||||
{-0.587785, -0.425325, 0.688191},
|
||||
{-0.309017, -0.500000, 0.809017},
|
||||
{-0.147621, -0.716567, 0.681718},
|
||||
{-0.425325, -0.688191, 0.587785},
|
||||
{-0.162460, -0.262866, 0.951056},
|
||||
{0.442863, -0.238856, 0.864188},
|
||||
{0.162460, -0.262866, 0.951056},
|
||||
{0.309017, -0.500000, 0.809017},
|
||||
{0.147621, -0.716567, 0.681718},
|
||||
{0.000000, -0.525731, 0.850651},
|
||||
{0.425325, -0.688191, 0.587785},
|
||||
{0.587785, -0.425325, 0.688191},
|
||||
{0.688191, -0.587785, 0.425325},
|
||||
{-0.955423, 0.295242, 0.000000},
|
||||
{-0.951056, 0.162460, 0.262866},
|
||||
{-1.000000, 0.000000, 0.000000},
|
||||
{-0.850651, 0.000000, 0.525731},
|
||||
{-0.955423, -0.295242, 0.000000},
|
||||
{-0.951056, -0.162460, 0.262866},
|
||||
{-0.864188, 0.442863, -0.238856},
|
||||
{-0.951056, 0.162460, -0.262866},
|
||||
{-0.809017, 0.309017, -0.500000},
|
||||
{-0.864188, -0.442863, -0.238856},
|
||||
{-0.951056, -0.162460, -0.262866},
|
||||
{-0.809017, -0.309017, -0.500000},
|
||||
{-0.681718, 0.147621, -0.716567},
|
||||
{-0.681718, -0.147621, -0.716567},
|
||||
{-0.850651, 0.000000, -0.525731},
|
||||
{-0.688191, 0.587785, -0.425325},
|
||||
{-0.587785, 0.425325, -0.688191},
|
||||
{-0.425325, 0.688191, -0.587785},
|
||||
{-0.425325, -0.688191, -0.587785},
|
||||
{-0.587785, -0.425325, -0.688191},
|
||||
{-0.688191, -0.587785, -0.425325},
|
||||
41
src/engine/archtypes.h
Normal file
41
src/engine/archtypes.h
Normal file
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// Word size dependent definitions
|
||||
// DAL 1/03
|
||||
//
|
||||
#ifndef ARCHTYPES_H
|
||||
#define ARCHTYPES_H
|
||||
|
||||
#ifdef __x86_64__
|
||||
#define X64BITS
|
||||
#endif
|
||||
|
||||
#if defined( _WIN32 ) && (! defined( __MINGW32__ ))
|
||||
|
||||
typedef __int16 int16;
|
||||
typedef unsigned __int16 uint16;
|
||||
typedef __int32 int32;
|
||||
typedef unsigned __int32 uint32;
|
||||
typedef __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
typedef __int32 intp; // intp is an integer that can accomodate a pointer
|
||||
typedef unsigned __int32 uintp; // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *)
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
typedef short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef int int32;
|
||||
typedef unsigned int uint32;
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
#ifdef X64BITS
|
||||
typedef long long intp;
|
||||
typedef unsigned long long uintp;
|
||||
#else
|
||||
typedef int intp;
|
||||
typedef unsigned int uintp;
|
||||
#endif
|
||||
|
||||
#endif /* else _WIN32 */
|
||||
|
||||
#endif /* ARCHTYPES_H */
|
||||
311
src/engine/cdll_int.h
Normal file
311
src/engine/cdll_int.h
Normal file
@@ -0,0 +1,311 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
//
|
||||
// cdll_int.h
|
||||
//
|
||||
// 4-23-98
|
||||
// JOHN: client dll interface declarations
|
||||
//
|
||||
|
||||
#ifndef CDLL_INT_H
|
||||
#define CDLL_INT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "const.h"
|
||||
|
||||
|
||||
// this file is included by both the engine and the client-dll,
|
||||
// so make sure engine declarations aren't done twice
|
||||
|
||||
typedef int HSPRITE; // handle to a graphic
|
||||
|
||||
#define SCRINFO_SCREENFLASH 1
|
||||
#define SCRINFO_STRETCHED 2
|
||||
|
||||
typedef struct SCREENINFO_s
|
||||
{
|
||||
int iSize;
|
||||
int iWidth;
|
||||
int iHeight;
|
||||
int iFlags;
|
||||
int iCharHeight;
|
||||
short charWidths[256];
|
||||
} SCREENINFO;
|
||||
|
||||
|
||||
typedef struct client_data_s
|
||||
{
|
||||
// fields that cannot be modified (ie. have no effect if changed)
|
||||
vec3_t origin;
|
||||
|
||||
// fields that can be changed by the cldll
|
||||
vec3_t viewangles;
|
||||
int iWeaponBits;
|
||||
float fov; // field of view
|
||||
} client_data_t;
|
||||
|
||||
typedef struct client_sprite_s
|
||||
{
|
||||
char szName[64];
|
||||
char szSprite[64];
|
||||
int hspr;
|
||||
int iRes;
|
||||
wrect_t rc;
|
||||
} client_sprite_t;
|
||||
|
||||
typedef struct client_textmessage_s
|
||||
{
|
||||
int effect;
|
||||
byte r1, g1, b1, a1; // 2 colors for effects
|
||||
byte r2, g2, b2, a2;
|
||||
float x;
|
||||
float y;
|
||||
float fadein;
|
||||
float fadeout;
|
||||
float holdtime;
|
||||
float fxtime;
|
||||
const char *pName;
|
||||
const char *pMessage;
|
||||
} client_textmessage_t;
|
||||
|
||||
typedef struct hud_player_info_s
|
||||
{
|
||||
char *name;
|
||||
short ping;
|
||||
byte thisplayer; // TRUE if this is the calling player
|
||||
|
||||
// stuff that's unused at the moment, but should be done
|
||||
byte spectator;
|
||||
byte packetloss;
|
||||
|
||||
char *model;
|
||||
short topcolor;
|
||||
short bottomcolor;
|
||||
|
||||
} hud_player_info_t;
|
||||
|
||||
|
||||
typedef struct cl_enginefuncs_s
|
||||
{
|
||||
// sprite handlers
|
||||
HSPRITE ( *pfnSPR_Load ) ( const char *szPicName );
|
||||
int ( *pfnSPR_Frames ) ( HSPRITE hPic );
|
||||
int ( *pfnSPR_Height ) ( HSPRITE hPic, int frame );
|
||||
int ( *pfnSPR_Width ) ( HSPRITE hPic, int frame );
|
||||
void ( *pfnSPR_Set ) ( HSPRITE hPic, int r, int g, int b );
|
||||
void ( *pfnSPR_Draw ) ( int frame, int x, int y, const wrect_t *prc );
|
||||
void ( *pfnSPR_DrawHoles ) ( int frame, int x, int y, const wrect_t *prc );
|
||||
void ( *pfnSPR_DrawAdditive ) ( int frame, int x, int y, const wrect_t *prc );
|
||||
void ( *pfnSPR_EnableScissor ) ( int x, int y, int width, int height );
|
||||
void ( *pfnSPR_DisableScissor ) ( void );
|
||||
client_sprite_t *( *pfnSPR_GetList ) ( char *psz, int *piCount );
|
||||
|
||||
// screen handlers
|
||||
void ( *pfnFillRGBA ) ( int x, int y, int width, int height, int r, int g, int b, int a );
|
||||
int ( *pfnGetScreenInfo ) ( SCREENINFO *pscrinfo );
|
||||
void ( *pfnSetCrosshair ) ( HSPRITE hspr, wrect_t rc, int r, int g, int b );
|
||||
|
||||
// cvar handlers
|
||||
struct cvar_s *( *pfnRegisterVariable ) ( char *szName, char *szValue, int flags );
|
||||
float ( *pfnGetCvarFloat ) ( char *szName );
|
||||
char* ( *pfnGetCvarString ) ( char *szName );
|
||||
|
||||
// command handlers
|
||||
int ( *pfnAddCommand ) ( char *cmd_name, void (*function)(void) );
|
||||
int ( *pfnHookUserMsg ) ( char *szMsgName, pfnUserMsgHook pfn );
|
||||
int ( *pfnServerCmd ) ( char *szCmdString );
|
||||
int ( *pfnClientCmd ) ( char *szCmdString );
|
||||
|
||||
void ( *pfnGetPlayerInfo ) ( int ent_num, hud_player_info_t *pinfo );
|
||||
|
||||
// sound handlers
|
||||
void ( *pfnPlaySoundByName ) ( char *szSound, float volume );
|
||||
void ( *pfnPlaySoundByIndex ) ( int iSound, float volume );
|
||||
|
||||
// vector helpers
|
||||
void ( *pfnAngleVectors ) ( const float * vecAngles, float * forward, float * right, float * up );
|
||||
|
||||
// text message system
|
||||
client_textmessage_t *( *pfnTextMessageGet ) ( const char *pName );
|
||||
int ( *pfnDrawCharacter ) ( int x, int y, int number, int r, int g, int b );
|
||||
int ( *pfnDrawConsoleString ) ( int x, int y, char *string );
|
||||
void ( *pfnDrawSetTextColor ) ( float r, float g, float b );
|
||||
void ( *pfnDrawConsoleStringLen )( const char *string, int *length, int *height );
|
||||
|
||||
void ( *pfnConsolePrint ) ( const char *string );
|
||||
void ( *pfnCenterPrint ) ( const char *string );
|
||||
|
||||
|
||||
// Added for user input processing
|
||||
int ( *GetWindowCenterX ) ( void );
|
||||
int ( *GetWindowCenterY ) ( void );
|
||||
void ( *GetViewAngles ) ( float * );
|
||||
void ( *SetViewAngles ) ( float * );
|
||||
int ( *GetMaxClients ) ( void );
|
||||
void ( *Cvar_SetValue ) ( char *cvar, float value );
|
||||
|
||||
int (*Cmd_Argc) (void);
|
||||
char *( *Cmd_Argv ) ( int arg );
|
||||
void ( *Con_Printf ) ( char *fmt, ... );
|
||||
void ( *Con_DPrintf ) ( char *fmt, ... );
|
||||
void ( *Con_NPrintf ) ( int pos, char *fmt, ... );
|
||||
void ( *Con_NXPrintf ) ( struct con_nprint_s *info, char *fmt, ... );
|
||||
|
||||
const char *( *PhysInfo_ValueForKey ) ( const char *key );
|
||||
const char *( *ServerInfo_ValueForKey )( const char *key );
|
||||
float ( *GetClientMaxspeed ) ( void );
|
||||
int ( *CheckParm ) ( char *parm, char **ppnext );
|
||||
void ( *Key_Event ) ( int key, int down );
|
||||
void ( *GetMousePosition ) ( int *mx, int *my );
|
||||
int ( *IsNoClipping ) ( void );
|
||||
|
||||
struct cl_entity_s *( *GetLocalPlayer ) ( void );
|
||||
struct cl_entity_s *( *GetViewModel ) ( void );
|
||||
struct cl_entity_s *( *GetEntityByIndex ) ( int idx );
|
||||
|
||||
float ( *GetClientTime ) ( void );
|
||||
void ( *V_CalcShake ) ( void );
|
||||
void ( *V_ApplyShake ) ( float *origin, float *angles, float factor );
|
||||
|
||||
int ( *PM_PointContents ) ( float *point, int *truecontents );
|
||||
int ( *PM_WaterEntity ) ( float *p );
|
||||
struct pmtrace_s *( *PM_TraceLine ) ( float *start, float *end, int flags, int usehull, int ignore_pe );
|
||||
|
||||
struct model_s *( *CL_LoadModel ) ( const char *modelname, int *index );
|
||||
int ( *CL_CreateVisibleEntity ) ( int type, struct cl_entity_s *ent );
|
||||
|
||||
const struct model_s * ( *GetSpritePointer ) ( HSPRITE hSprite );
|
||||
void ( *pfnPlaySoundByNameAtLocation ) ( char *szSound, float volume, float *origin );
|
||||
|
||||
unsigned short ( *pfnPrecacheEvent ) ( int type, const char* psz );
|
||||
void ( *pfnPlaybackEvent ) ( int flags, const struct edict_s *pInvoker, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2 );
|
||||
void ( *pfnWeaponAnim ) ( int iAnim, int body );
|
||||
float ( *pfnRandomFloat ) ( float flLow, float flHigh );
|
||||
long ( *pfnRandomLong ) ( long lLow, long lHigh );
|
||||
void ( *pfnHookEvent ) ( char *name, void ( *pfnEvent )( struct event_args_s *args ) );
|
||||
int (*Con_IsVisible) ();
|
||||
const char *( *pfnGetGameDirectory ) ( void );
|
||||
struct cvar_s *( *pfnGetCvarPointer ) ( const char *szName );
|
||||
const char *( *Key_LookupBinding ) ( const char *pBinding );
|
||||
const char *( *pfnGetLevelName ) ( void );
|
||||
void ( *pfnGetScreenFade ) ( struct screenfade_s *fade );
|
||||
void ( *pfnSetScreenFade ) ( struct screenfade_s *fade );
|
||||
void *( *VGui_GetPanel ) ( );
|
||||
void ( *VGui_ViewportPaintBackground ) (int extents[4]);
|
||||
|
||||
byte* (*COM_LoadFile) ( char *path, int usehunk, int *pLength );
|
||||
char* (*COM_ParseFile) ( char *data, char *token );
|
||||
void (*COM_FreeFile) ( void *buffer );
|
||||
|
||||
struct triangleapi_s *pTriAPI;
|
||||
struct efx_api_s *pEfxAPI;
|
||||
struct event_api_s *pEventAPI;
|
||||
struct demo_api_s *pDemoAPI;
|
||||
struct net_api_s *pNetAPI;
|
||||
struct IVoiceTweak_s *pVoiceTweak;
|
||||
|
||||
// returns 1 if the client is a spectator only (connected to a proxy), 0 otherwise or 2 if in dev_overview mode
|
||||
int ( *IsSpectateOnly ) ( void );
|
||||
struct model_s *( *LoadMapSprite ) ( const char *filename );
|
||||
|
||||
// file search functions
|
||||
void ( *COM_AddAppDirectoryToSearchPath ) ( const char *pszBaseDir, const char *appName );
|
||||
int ( *COM_ExpandFilename) ( const char *fileName, char *nameOutBuffer, int nameOutBufferSize );
|
||||
|
||||
// User info
|
||||
// playerNum is in the range (1, MaxClients)
|
||||
// returns NULL if player doesn't exit
|
||||
// returns "" if no value is set
|
||||
const char *( *PlayerInfo_ValueForKey )( int playerNum, const char *key );
|
||||
void ( *PlayerInfo_SetValueForKey )( const char *key, const char *value );
|
||||
|
||||
// Gets a unique ID for the specified player. This is the same even if you see the player on a different server.
|
||||
// iPlayer is an entity index, so client 0 would use iPlayer=1.
|
||||
// Returns false if there is no player on the server in the specified slot.
|
||||
qboolean (*GetPlayerUniqueID)(int iPlayer, char playerID[16]);
|
||||
|
||||
// TrackerID access
|
||||
int (*GetTrackerIDForPlayer)(int playerSlot);
|
||||
int (*GetPlayerForTrackerID)(int trackerID);
|
||||
|
||||
// Same as pfnServerCmd, but the message goes in the unreliable stream so it can't clog the net stream
|
||||
// (but it might not get there).
|
||||
int ( *pfnServerCmdUnreliable )( char *szCmdString );
|
||||
|
||||
void ( *pfnGetMousePos )( struct tagPOINT *ppt );
|
||||
void ( *pfnSetMousePos )( int x, int y );
|
||||
void ( *pfnSetMouseEnable )( qboolean fEnable );
|
||||
} cl_enginefunc_t;
|
||||
|
||||
#ifndef IN_BUTTONS_H
|
||||
#include "in_buttons.h"
|
||||
#endif
|
||||
|
||||
#define CLDLL_INTERFACE_VERSION 7
|
||||
|
||||
extern void ClientDLL_Init( void ); // from cdll_int.c
|
||||
extern void ClientDLL_Shutdown( void );
|
||||
extern void ClientDLL_HudInit( void );
|
||||
extern void ClientDLL_HudVidInit( void );
|
||||
extern void ClientDLL_UpdateClientData( void );
|
||||
extern void ClientDLL_Frame( double time );
|
||||
extern void ClientDLL_HudRedraw( int intermission );
|
||||
extern void ClientDLL_MoveClient( struct playermove_s *ppmove );
|
||||
extern void ClientDLL_ClientMoveInit( struct playermove_s *ppmove );
|
||||
extern char ClientDLL_ClientTextureType( char *name );
|
||||
|
||||
extern void ClientDLL_CreateMove( float frametime, struct usercmd_s *cmd, int active );
|
||||
extern void ClientDLL_ActivateMouse( void );
|
||||
extern void ClientDLL_DeactivateMouse( void );
|
||||
extern void ClientDLL_MouseEvent( int mstate );
|
||||
extern void ClientDLL_ClearStates( void );
|
||||
extern int ClientDLL_IsThirdPerson( void );
|
||||
extern void ClientDLL_GetCameraOffsets( float *ofs );
|
||||
extern int ClientDLL_GraphKeyDown( void );
|
||||
extern struct kbutton_s *ClientDLL_FindKey( const char *name );
|
||||
extern void ClientDLL_CAM_Think( void );
|
||||
extern void ClientDLL_IN_Accumulate( void );
|
||||
extern void ClientDLL_CalcRefdef( struct ref_params_s *pparams );
|
||||
extern int ClientDLL_AddEntity( int type, struct cl_entity_s *ent );
|
||||
extern void ClientDLL_CreateEntities( void );
|
||||
|
||||
extern void ClientDLL_DrawNormalTriangles( void );
|
||||
extern void ClientDLL_DrawTransparentTriangles( void );
|
||||
extern void ClientDLL_StudioEvent( const struct mstudioevent_s *event, const struct cl_entity_s *entity );
|
||||
extern void ClientDLL_PostRunCmd( struct local_state_s *from, struct local_state_s *to, struct usercmd_s *cmd, int runfuncs, double time, unsigned int random_seed );
|
||||
extern void ClientDLL_TxferLocalOverrides( struct entity_state_s *state, const struct clientdata_s *client );
|
||||
extern void ClientDLL_ProcessPlayerState( struct entity_state_s *dst, const struct entity_state_s *src );
|
||||
extern void ClientDLL_TxferPredictionData ( struct entity_state_s *ps, const struct entity_state_s *pps, struct clientdata_s *pcd, const struct clientdata_s *ppcd, struct weapon_data_s *wd, const struct weapon_data_s *pwd );
|
||||
extern void ClientDLL_ReadDemoBuffer( int size, unsigned char *buffer );
|
||||
extern int ClientDLL_ConnectionlessPacket( const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size );
|
||||
extern int ClientDLL_GetHullBounds( int hullnumber, float *mins, float *maxs );
|
||||
|
||||
extern void ClientDLL_VGui_ConsolePrint(const char* text);
|
||||
|
||||
extern int ClientDLL_Key_Event( int down, int keynum, const char *pszCurrentBinding );
|
||||
extern void ClientDLL_TempEntUpdate( double ft, double ct, double grav, struct tempent_s **ppFreeTE, struct tempent_s **ppActiveTE, int ( *addTEntity )( struct cl_entity_s *pEntity ), void ( *playTESound )( struct tempent_s *pTemp, float damp ) );
|
||||
extern struct cl_entity_s *ClientDLL_GetUserEntity( int index );
|
||||
extern void ClientDLL_VoiceStatus(int entindex, qboolean bTalking);
|
||||
extern void ClientDLL_DirectorMessage( int iSize, void *pbuf );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // CDLL_INT_H
|
||||
@@ -17,7 +17,9 @@
|
||||
#ifndef CUSTOM_H
|
||||
#define CUSTOM_H
|
||||
#ifdef _WIN32
|
||||
#ifndef __MINGW32__
|
||||
#pragma once
|
||||
#endif /* not __MINGW32__ */
|
||||
#endif
|
||||
|
||||
#include "const.h"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2001, Valve LLC. All rights reserved.
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
131
src/engine/keydefs.h
Normal file
@@ -0,0 +1,131 @@
|
||||
//========= Copyright <20> 1996-2002, Valve LLC, All rights reserved. ============
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================
|
||||
|
||||
// keydefs.h
|
||||
#ifndef KEYDEFS_H
|
||||
#define KEYDEFS_H
|
||||
#ifdef _WIN32
|
||||
#ifndef __MINGW32__
|
||||
#pragma once
|
||||
#endif /* not __MINGW32__ */
|
||||
#endif
|
||||
|
||||
//
|
||||
// these are the key numbers that should be passed to Key_Event
|
||||
//
|
||||
#define K_TAB 9
|
||||
#define K_ENTER 13
|
||||
#define K_ESCAPE 27
|
||||
#define K_SPACE 32
|
||||
|
||||
// normal keys should be passed as lowercased ascii
|
||||
|
||||
#define K_BACKSPACE 127
|
||||
#define K_UPARROW 128
|
||||
#define K_DOWNARROW 129
|
||||
#define K_LEFTARROW 130
|
||||
#define K_RIGHTARROW 131
|
||||
|
||||
#define K_ALT 132
|
||||
#define K_CTRL 133
|
||||
#define K_SHIFT 134
|
||||
#define K_F1 135
|
||||
#define K_F2 136
|
||||
#define K_F3 137
|
||||
#define K_F4 138
|
||||
#define K_F5 139
|
||||
#define K_F6 140
|
||||
#define K_F7 141
|
||||
#define K_F8 142
|
||||
#define K_F9 143
|
||||
#define K_F10 144
|
||||
#define K_F11 145
|
||||
#define K_F12 146
|
||||
#define K_INS 147
|
||||
#define K_DEL 148
|
||||
#define K_PGDN 149
|
||||
#define K_PGUP 150
|
||||
#define K_HOME 151
|
||||
#define K_END 152
|
||||
|
||||
#define K_KP_HOME 160
|
||||
#define K_KP_UPARROW 161
|
||||
#define K_KP_PGUP 162
|
||||
#define K_KP_LEFTARROW 163
|
||||
#define K_KP_5 164
|
||||
#define K_KP_RIGHTARROW 165
|
||||
#define K_KP_END 166
|
||||
#define K_KP_DOWNARROW 167
|
||||
#define K_KP_PGDN 168
|
||||
#define K_KP_ENTER 169
|
||||
#define K_KP_INS 170
|
||||
#define K_KP_DEL 171
|
||||
#define K_KP_SLASH 172
|
||||
#define K_KP_MINUS 173
|
||||
#define K_KP_PLUS 174
|
||||
#define K_CAPSLOCK 175
|
||||
|
||||
|
||||
//
|
||||
// joystick buttons
|
||||
//
|
||||
#define K_JOY1 203
|
||||
#define K_JOY2 204
|
||||
#define K_JOY3 205
|
||||
#define K_JOY4 206
|
||||
|
||||
//
|
||||
// aux keys are for multi-buttoned joysticks to generate so they can use
|
||||
// the normal binding process
|
||||
//
|
||||
#define K_AUX1 207
|
||||
#define K_AUX2 208
|
||||
#define K_AUX3 209
|
||||
#define K_AUX4 210
|
||||
#define K_AUX5 211
|
||||
#define K_AUX6 212
|
||||
#define K_AUX7 213
|
||||
#define K_AUX8 214
|
||||
#define K_AUX9 215
|
||||
#define K_AUX10 216
|
||||
#define K_AUX11 217
|
||||
#define K_AUX12 218
|
||||
#define K_AUX13 219
|
||||
#define K_AUX14 220
|
||||
#define K_AUX15 221
|
||||
#define K_AUX16 222
|
||||
#define K_AUX17 223
|
||||
#define K_AUX18 224
|
||||
#define K_AUX19 225
|
||||
#define K_AUX20 226
|
||||
#define K_AUX21 227
|
||||
#define K_AUX22 228
|
||||
#define K_AUX23 229
|
||||
#define K_AUX24 230
|
||||
#define K_AUX25 231
|
||||
#define K_AUX26 232
|
||||
#define K_AUX27 233
|
||||
#define K_AUX28 234
|
||||
#define K_AUX29 235
|
||||
#define K_AUX30 236
|
||||
#define K_AUX31 237
|
||||
#define K_AUX32 238
|
||||
#define K_MWHEELDOWN 239
|
||||
#define K_MWHEELUP 240
|
||||
|
||||
#define K_PAUSE 255
|
||||
|
||||
//
|
||||
// mouse buttons generate virtual keys
|
||||
//
|
||||
#define K_MOUSE1 241
|
||||
#define K_MOUSE2 242
|
||||
#define K_MOUSE3 243
|
||||
#define K_MOUSE4 244
|
||||
#define K_MOUSE5 245
|
||||
|
||||
#endif // KEYDEFS_H
|
||||
@@ -15,7 +15,9 @@
|
||||
#ifndef PROGDEFS_H
|
||||
#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
82
src/engine/progs.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
#ifndef PROGS_H
|
||||
#define PROGS_H
|
||||
|
||||
#include "progdefs.h"
|
||||
|
||||
// 16 simultaneous events, max
|
||||
#define MAX_EVENT_QUEUE 64
|
||||
|
||||
#define DEFAULT_EVENT_RESENDS 1
|
||||
|
||||
#include "event_flags.h"
|
||||
|
||||
typedef struct event_info_s event_info_t;
|
||||
|
||||
#include "event_args.h"
|
||||
|
||||
struct event_info_s
|
||||
{
|
||||
unsigned short index; // 0 implies not in use
|
||||
|
||||
short packet_index; // Use data from state info for entity in delta_packet . -1 implies separate info based on event
|
||||
// parameter signature
|
||||
short entity_index; // The edict this event is associated with
|
||||
|
||||
float fire_time; // if non-zero, the time when the event should be fired ( fixed up on the client )
|
||||
|
||||
event_args_t args;
|
||||
|
||||
// CLIENT ONLY
|
||||
int flags; // Reliable or not, etc.
|
||||
|
||||
};
|
||||
|
||||
typedef struct event_state_s event_state_t;
|
||||
|
||||
struct event_state_s
|
||||
{
|
||||
struct event_info_s ei[ MAX_EVENT_QUEUE ];
|
||||
};
|
||||
|
||||
#if !defined( ENTITY_STATEH )
|
||||
#include "entity_state.h"
|
||||
#endif
|
||||
|
||||
#if !defined( EDICT_H )
|
||||
#include "edict.h"
|
||||
#endif
|
||||
|
||||
#define STRUCT_FROM_LINK(l,t,m) ((t *)((byte *)l - (int)&(((t *)0)->m)))
|
||||
#define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,edict_t,area)
|
||||
|
||||
//============================================================================
|
||||
|
||||
extern char *pr_strings;
|
||||
extern globalvars_t gGlobalVariables;
|
||||
|
||||
//============================================================================
|
||||
|
||||
edict_t *ED_Alloc (void);
|
||||
void ED_Free (edict_t *ed);
|
||||
void ED_LoadFromFile (char *data);
|
||||
|
||||
edict_t *EDICT_NUM(int n);
|
||||
int NUM_FOR_EDICT(const edict_t *e);
|
||||
|
||||
#define PROG_TO_EDICT(e) ((edict_t *)((byte *)sv.edicts + e))
|
||||
|
||||
#endif // PROGS_H
|
||||
@@ -1,6 +1,6 @@
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, Valve LLC. All rights reserved.
|
||||
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
|
||||
3
src/metamod/.gitignore
vendored
3
src/metamod/.gitignore
vendored
@@ -1,3 +0,0 @@
|
||||
msgs/
|
||||
opt.*/
|
||||
debug.*/
|
||||
@@ -1,34 +0,0 @@
|
||||
MODNAME = metamod
|
||||
|
||||
#__METAMOD_BUILD__ for our special eiface.h
|
||||
EXTRA_CFLAGS += -D__METAMOD_BUILD__
|
||||
#-DMETA_PERFMON
|
||||
|
||||
SRCFILES = api_hook.cpp api_info.cpp commands_meta.cpp conf_meta.cpp \
|
||||
dllapi.cpp engine_api.cpp engineinfo.cpp game_support.cpp \
|
||||
game_autodetect.cpp h_export.cpp linkgame.cpp linkplug.cpp \
|
||||
log_meta.cpp meta_eiface.cpp metamod.cpp mlist.cpp mplayer.cpp \
|
||||
mplugin.cpp mqueue.cpp mreg.cpp mutil.cpp osdep.cpp \
|
||||
osdep_p.cpp reg_support.cpp sdk_util.cpp studioapi.cpp \
|
||||
support_meta.cpp thread_logparse.cpp vdate.cpp
|
||||
|
||||
INFOFILES = info_name.h vers_meta.h
|
||||
RESFILE = res_meta.rc
|
||||
|
||||
ifeq "$(OS)" "linux"
|
||||
SRCFILES+=osdep_linkent_linux.cpp osdep_detect_gamedll_linux.cpp
|
||||
EXTRA_LINK+=
|
||||
else
|
||||
SRCFILES+=osdep_linkent_win32.cpp osdep_detect_gamedll_win32.cpp
|
||||
EXTRA_LINK+=-Xlinker --script -Xlinker i386pe.merge
|
||||
endif
|
||||
|
||||
ifeq "$(OPT)" "opt"
|
||||
EXTRA_CFLAGS += -D__INTERNALS_USE_REGPARAMS__
|
||||
endif
|
||||
|
||||
ifeq "$(OPT)" "opt-fast"
|
||||
EXTRA_CFLAGS += -D__INTERNALS_USE_REGPARAMS__
|
||||
endif
|
||||
|
||||
#STLFILES = mreg.cpp
|
||||
@@ -1,460 +0,0 @@
|
||||
# vi: set ts=4 sw=4 :
|
||||
# vim: set tw=75 :
|
||||
|
||||
# MetaMod makefile
|
||||
# Copyright (c) 2001-2003 Will Day <willday@hpgx.net>
|
||||
#
|
||||
# based on the Valve SDK 2.1 Makefile as well as the Makefile
|
||||
# in adminmod by Alfred Reynolds.
|
||||
#
|
||||
# From SDK 2.1 dlls/Makefile:
|
||||
#! Half-Life StandardSDK 2.0 mp_i386.so Makefile for i386 Linux
|
||||
#! April 2000 by Leon Hartwig (jehannum@planethalflife.com)
|
||||
|
||||
|
||||
# NOTE: This is a generic Makefile for metamod and the bundled plugins, and
|
||||
# is symlinked into each subdir. Per-module config statements are in
|
||||
# Config.mak in each subdir.
|
||||
|
||||
ifeq "$(shell uname | cut -d _ -f1)" "CYGWIN"
|
||||
HOST=cygwin
|
||||
endif
|
||||
|
||||
ifdef COMSPEC
|
||||
ifeq "$(HOST)" "cygwin"
|
||||
ifeq "$(TARGET)" "win32"
|
||||
OS=windows
|
||||
else
|
||||
OS=linux
|
||||
endif
|
||||
else
|
||||
OS=windows
|
||||
endif
|
||||
else
|
||||
OS=linux
|
||||
endif
|
||||
|
||||
#############################################################################
|
||||
# CONFIGURATION
|
||||
#############################################################################
|
||||
|
||||
# TARGET amd64 disabled since Valve has dropped support for x86-64 server
|
||||
#ifeq "$(TARGET)" "amd64"
|
||||
# TARGETTYPE = amd64
|
||||
#else
|
||||
TARGETTYPE = i386
|
||||
#endif
|
||||
|
||||
# set paths for your environment
|
||||
ifeq "$(OS)" "linux"
|
||||
INST_DIR=$(HOME)/half-life/cstrike/dlls
|
||||
TEST_DIR=$(HOME)/test/tfc/dlls
|
||||
TST_DIR=$(HOME)/tmp
|
||||
else ## windows
|
||||
INST_DIR=/hlserver/tfc/dlls
|
||||
TEST_DIR=/hlserver/tfc/dlls
|
||||
endif
|
||||
|
||||
DLLS_DIR=../dlls
|
||||
SDKSRC=../hlsdk
|
||||
METADIR=../metamod
|
||||
|
||||
COMPILE_TZ=EET
|
||||
## Developer overrides
|
||||
ifeq "$(USER)" "jussi"
|
||||
COMPILE_TZ=EET
|
||||
endif
|
||||
|
||||
|
||||
#############################################################################
|
||||
# OS DEPENDENCIES
|
||||
#############################################################################
|
||||
|
||||
ifeq "$(OS)" "linux"
|
||||
INSTALL=install -m 644
|
||||
LD_WINDLL= i686-w64-mingw32-dllwrap
|
||||
OSTARGET=linux
|
||||
LIBFILE=$(LIBFILE_LINUX)
|
||||
TARGET_FILE=$(TARGET_LINUX)
|
||||
else ## windows
|
||||
INSTALL=cp
|
||||
LD_WINDLL= i686-w64-mingw32-dllwrap
|
||||
OSTARGET=win32
|
||||
LIBFILE=$(LIBFILE_WIN)
|
||||
TARGET_FILE=$(TARGET_WIN)
|
||||
endif
|
||||
|
||||
CC_WIN=i686-w64-mingw32-gcc
|
||||
RES_WIN=i686-w64-mingw32-windres
|
||||
|
||||
ifeq "$(HOST)" "cygwin"
|
||||
CC_WIN += -mno-cygwin
|
||||
EXTRA_LINK += -L/lib/w32api
|
||||
endif
|
||||
|
||||
OBJDIR_LINUX_OPT=opt.linux_$(TARGETTYPE)
|
||||
OBJDIR_LINUX_DBG=debug.linux_$(TARGETTYPE)
|
||||
OBJDIR_WIN_OPT=opt.win32
|
||||
OBJDIR_WIN_DBG=debug.win32
|
||||
|
||||
|
||||
#############################################################################
|
||||
# COMPILE OPTIONS - ARCHITECTURE AND OPTIMIZATIONS
|
||||
#############################################################################
|
||||
|
||||
ifeq "$(OS)" "linux"
|
||||
GCCMAJ = $(shell $(CC) -dumpversion | sed -e 's/\.[0-9][0-9]*//' -e 's/\.[0-9][0-9]*//')
|
||||
GCCMIN = $(shell $(CC) -dumpversion | sed -e 's/[0-9]\.//;s/\.[0-9]//' -e 's/\.[0-9][0-9]*//')
|
||||
else
|
||||
GCCMAJ = $(shell $(CC_WIN) -dumpversion | sed -e 's/\.[0-9][0-9]*//' -e 's/\.[0-9][0-9]*//')
|
||||
GCCMIN = $(shell $(CC_WIN) -dumpversion | sed -e 's/[0-9]\.//;s/\.[0-9]//' -e 's/\.[0-9][0-9]*//')
|
||||
endif
|
||||
|
||||
GCCMAJ_GT_4 = $(shell if [ $(GCCMAJ) -gt 4 ]; then echo 1; else echo 0; fi)
|
||||
|
||||
ifeq "$(HOST)" "cygwin"
|
||||
ifeq "$(TARGETTYPE)" "amd64"
|
||||
CC=gcc-linux-x86_64
|
||||
else
|
||||
CC=gcc-linux
|
||||
endif
|
||||
else
|
||||
ifeq "$(TARGETTYPE)" "amd64"
|
||||
CC=gcc -m64
|
||||
else
|
||||
CC=gcc -m32
|
||||
endif
|
||||
endif
|
||||
|
||||
MCPU=-mcpu
|
||||
|
||||
ifeq "$(GCCMAJ)" "3"
|
||||
ifeq "$(GCCMIN)" "4"
|
||||
MCPU=-mtune
|
||||
endif
|
||||
endif
|
||||
ifeq "$(GCCMAJ)" "4"
|
||||
MCPU=-mtune
|
||||
endif
|
||||
ifeq "$(GCCMAJ_GT_4)" "1"
|
||||
MCPU=-mtune
|
||||
endif
|
||||
|
||||
ifeq "$(OS)" "linux"
|
||||
CC_DEP=$(CC)
|
||||
else
|
||||
CC_DEP=$(CC_WIN)
|
||||
endif
|
||||
|
||||
# Note! About gcc optimization levels.
|
||||
# There is four optimization levels:
|
||||
# -O0 No optimizations.
|
||||
# -O1 Optimize for smaller size.
|
||||
# -O2 Optimize for speed without increasing size (alot).
|
||||
# -O3 Optimize for speed, can result much greater filesize.
|
||||
# Levels higher -O3 (-O6 for example) is threaded as -O3.
|
||||
# See differences at "http://gcc.gnu.org/" (look for link to 'gcc manual').
|
||||
|
||||
# original safe optimization, from valve Makefile
|
||||
#CCOPT = -O2 -ffast-math -funroll-loops \
|
||||
# -fomit-frame-pointer -fexpensive-optimizations -malign-loops=2 \
|
||||
# -malign-jumps=2 -malign-functions=2
|
||||
|
||||
# safe optimization, adapted from adminmod Makefile
|
||||
#CCOPT = -m486 -O6 -ffast-math -funroll-loops \
|
||||
# -fexpensive-optimizations -malign-loops=2 -malign-jumps=2 \
|
||||
# -malign-functions=2 -Wall
|
||||
|
||||
# full optimization, adapted from adminmod Makefile
|
||||
# "WONT WORK WITH omit-frame-pointer"?
|
||||
# - disable (unneeded) C++ exceptions and rtti code to save some space ?
|
||||
|
||||
CCOPT = $(CCO) $(CCOPT_ARCH) -fno-exceptions -fno-rtti
|
||||
|
||||
# optimization level; overridden for certain problematic files
|
||||
CCO = -O2 -fomit-frame-pointer -funsafe-math-optimizations
|
||||
CCO += -flto -fvisibility=hidden
|
||||
|
||||
# architecture tuning by target type
|
||||
ifeq "$(TARGETTYPE)" "amd64"
|
||||
CCOPT_ARCH =
|
||||
else
|
||||
CCOPT_ARCH = -march=i686 $(MCPU)=generic -msse -msse2
|
||||
endif
|
||||
|
||||
# debugging; halt on warnings
|
||||
CCDEBUG+= -ggdb3
|
||||
|
||||
|
||||
#############################################################################
|
||||
# COMPILE SETUP
|
||||
#############################################################################
|
||||
|
||||
SRCDIR=.
|
||||
INCLUDEDIRS+=-I$(SRCDIR) -I$(METADIR) -I$(SDKSRC)/engine -I$(SDKSRC)/common -I$(SDKSRC)/pm_shared -I$(SDKSRC)/dlls -I$(SDKSRC)
|
||||
FILES_ALL = *.cpp *.h [A-Z]* *.rc
|
||||
|
||||
CFLAGS=-Wall -Wno-unknown-pragmas -Wno-attributes -Wno-write-strings
|
||||
|
||||
CFLAGS+=-std=gnu++98 -Wno-c++11-compat
|
||||
|
||||
#CFLAGS += -DTEST
|
||||
|
||||
ifeq "$(OPT)" "opt-fast"
|
||||
ODEF = -DOPT_TYPE="\"optimized+meta_debug-disabled\""
|
||||
CFLAGS := $(CCOPT) $(CFLAGS) $(ODEF) -D__BUILD_FAST_METAMOD__
|
||||
OBJDIR_LINUX = $(OBJDIR_LINUX_OPT)
|
||||
OBJDIR_WIN = $(OBJDIR_WIN_OPT)
|
||||
else #other
|
||||
ifeq "$(OPT)" "opt"
|
||||
ODEF = -DOPT_TYPE="\"optimized\""
|
||||
CFLAGS := $(CCOPT) $(CFLAGS) $(ODEF)
|
||||
OBJDIR_LINUX = $(OBJDIR_LINUX_OPT)
|
||||
OBJDIR_WIN = $(OBJDIR_WIN_OPT)
|
||||
else # debug
|
||||
ODEF = -DOPT_TYPE="\"debugging\""
|
||||
CFLAGS := $(CCDEBUG) $(CFLAGS) $(ODEF)
|
||||
OBJDIR_LINUX = $(OBJDIR_LINUX_DBG)
|
||||
OBJDIR_WIN = $(OBJDIR_WIN_DBG)
|
||||
DLLS_DIR := $(DLLS_DIR)/debug
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq "$(OS)" "linux"
|
||||
OBJDIR = $(OBJDIR_LINUX)
|
||||
else
|
||||
OBJDIR = $(OBJDIR_WIN)
|
||||
endif
|
||||
|
||||
include Config.mak
|
||||
# any local CFLAGS from Config.mak
|
||||
CFLAGS += $(EXTRA_CFLAGS)
|
||||
|
||||
# provide timezone info
|
||||
$(OBJDIR_LINUX)/vdate.o $(OBJDIR_WIN)/vdate.o: CFLAGS += -DCOMPILE_TZ=\"$(COMPILE_TZ)\"
|
||||
|
||||
# ignore complaints from SDK files like cbase.h
|
||||
#$(OBJDIR_LINUX)/sdk_util.o $(OBJDIR_WIN)/sdk_util.o: CFLAGS += -Wno-unused
|
||||
|
||||
# ignore complaints from STL headers
|
||||
STLOBJ = $(STLFILES:%.cpp=$(OBJDIR_LINUX)/%.o)
|
||||
STLOBJ += $(STLFILES:%.cpp=$(OBJDIR_WIN)/%.o)
|
||||
#$(OBJDIR_LINUX)/mreg.o $(OBJDIR_WIN)/mreg.o: CFLAGS += -Wno-effc++
|
||||
$(STLOBJ): FILTER= 2>&1 | ../tools/stlfilter
|
||||
$(STLOBJ): CFLAGS += -Wno-error
|
||||
|
||||
# these files seem to create "Internal compiler error" errors under mingw
|
||||
# when using -O6
|
||||
#$(OBJDIR_WIN)/engine_api.o: CCO = -O5
|
||||
#$(OBJDIR_WIN)/dllapi_api.o: CCO = -O5
|
||||
|
||||
#############################################################################
|
||||
# BUILDING LINUX SO
|
||||
#############################################################################
|
||||
|
||||
# linux .so compile commands
|
||||
DO_CC_LINUX=$(CC) $(CFLAGS) -fPIC $(INCLUDEDIRS) -o $@ -c $< $(FILTER)
|
||||
LINK_LINUX=$(CC) $(CFLAGS) -shared -ldl -lm -static-libgcc $(EXTRA_LINK) $(OBJ_LINUX) -o $@
|
||||
|
||||
# sort by date
|
||||
#SRCFILES := $(shell ls -t $(SRCFILES))
|
||||
|
||||
# linux object files
|
||||
OBJ_LINUX := $(SRCFILES:%.cpp=$(OBJDIR_LINUX)/%.o)
|
||||
|
||||
# compiling linux object files
|
||||
$(OBJDIR_LINUX)/%.o: $(SRCDIR)/%.cpp
|
||||
$(DO_CC_LINUX)
|
||||
|
||||
# linux .so target file
|
||||
LIBFILE_LINUX = $(MODNAME).so
|
||||
TARGET_LINUX = $(OBJDIR_LINUX)/$(LIBFILE_LINUX)
|
||||
|
||||
|
||||
#############################################################################
|
||||
# BUILDING WINDOWS DLL
|
||||
#############################################################################
|
||||
|
||||
# windows .dll compile commands
|
||||
DO_CC_WIN=$(CC_WIN) $(CFLAGS) $(INCLUDEDIRS) -o $@ -c $<
|
||||
DO_RES_WIN=$(RES_WIN) '$(ODEF)' --include-dir . --include-dir ../metamod -i $< -O coff -o $@
|
||||
#LINK_WIN=$(LD_WINDLL) -k -mwindows --add-stdcall-alias --def metamod.def -o $@ $(OBJ_WIN)
|
||||
#LINK_WIN=$(LD_WINDLL) -A -k -mwindows --export-all-symbols -o $@ $(OBJ_WIN)
|
||||
#LINK_WIN=$(LD_WINDLL) -mwindows --add-stdcall-alias $(OBJ_WIN) $(RES_OBJ_WIN) -lstdc++ -s -o $@
|
||||
LINK_WIN=$(CC_WIN) $(CFLAGS) -mdll -Xlinker --add-stdcall-alias $(EXTRA_LINK) $(OBJ_WIN) $(RES_OBJ_WIN) -s -o $@
|
||||
|
||||
# windows object files
|
||||
OBJ_WIN := $(SRCFILES:%.cpp=$(OBJDIR_WIN)/%.o)
|
||||
RES_OBJ_WIN := $(RESFILE:%.rc=$(OBJDIR_WIN)/%.o)
|
||||
|
||||
# compiling windows object files
|
||||
$(OBJDIR_WIN)/%.o: $(SRCDIR)/%.cpp
|
||||
$(DO_CC_WIN)
|
||||
|
||||
# compiling windows resource file
|
||||
$(OBJDIR_WIN)/%.o: $(SRCDIR)/%.rc $(INFOFILES)
|
||||
$(DO_RES_WIN)
|
||||
|
||||
# windows .dll target file
|
||||
LIBFILE_WIN = $(MODNAME).dll
|
||||
TARGET_WIN = $(OBJDIR_WIN)/$(LIBFILE_WIN)
|
||||
|
||||
|
||||
#############################################################################
|
||||
# OVERRIDES
|
||||
#############################################################################
|
||||
|
||||
ifeq "$(PLATFORM)" "linux-only"
|
||||
LIBFILE_WIN =
|
||||
TARGET_WIN =
|
||||
endif
|
||||
ifeq "$(PLATFORM)" "win32-only"
|
||||
LIBFILE_LINUX =
|
||||
TARGET_LINUX =
|
||||
OSTARGET=win32
|
||||
LIBFILE=$(LIBFILE_WIN)
|
||||
TARGET_FILE=$(TARGET_WIN)
|
||||
endif
|
||||
|
||||
|
||||
#############################################################################
|
||||
# BUILD RULES
|
||||
#############################################################################
|
||||
|
||||
default: $(TARGET_FILE)
|
||||
|
||||
all: do_dll_linux do_dll_win32
|
||||
|
||||
opt:
|
||||
$(MAKE) default OPT=opt
|
||||
|
||||
linux: do_dll_linux
|
||||
win32: do_dll_win32
|
||||
|
||||
linux_opt:
|
||||
$(MAKE) linux OPT=opt
|
||||
win32_opt:
|
||||
$(MAKE) win32 OPT=opt
|
||||
|
||||
$(TARGET_LINUX): msgs/debug msgs/warning msgs/log msgs/error $(OBJDIR_LINUX) $(OBJ_LINUX)
|
||||
$(LINK_LINUX)
|
||||
|
||||
# for plugins, recompile meta_api.cpp if info_name.h changed
|
||||
$(OBJDIR_LINUX)/meta_api.o $(OBJDIR_WIN)/meta_api.o: info_name.h
|
||||
|
||||
$(TARGET_WIN): msgs/debug msgs/warning msgs/log msgs/error $(OBJDIR_WIN) $(OBJ_WIN) $(RES_OBJ_WIN)
|
||||
$(LINK_WIN)
|
||||
|
||||
$(OBJDIR_LINUX) $(OBJDIR_WIN) msgs:
|
||||
mkdir $@
|
||||
|
||||
# make sure to recompile vdate.c for each link
|
||||
$(OBJDIR_LINUX)/vdate.o $(OBJDIR_WIN)/vdate.o : $(SRCFILES) *.h
|
||||
|
||||
domsgs: msgs/debug msgs/log msgs/error msgs/warning
|
||||
|
||||
msgs/debug: $(SRCFILES) *.h msgs
|
||||
egrep "DEBUG\([0-9]" $(SRCFILES) *.h | sed "s/:[ ]*/ /" | sort -k2,2 > $@
|
||||
|
||||
msgs/log: $(SRCFILES) *.h msgs
|
||||
egrep "META_LOG\(" $(SRCFILES) *.h | sed "s/:[ ]*/ /" | sort > $@
|
||||
|
||||
msgs/error: $(SRCFILES) *.h msgs
|
||||
egrep "META_ERROR\(" $(SRCFILES) *.h | sed "s/:[ ]*/ /" | sort > $@
|
||||
|
||||
msgs/warning: $(SRCFILES) *.h msgs
|
||||
egrep "META_WARNING\(" $(SRCFILES) *.h | sed "s/:[ ]*/ /" | sort > $@
|
||||
|
||||
tags: .tags .htags
|
||||
ctags: .tags
|
||||
htags: .htags
|
||||
|
||||
.tags: $(SRCFILES) *.h
|
||||
-ctags -a $?
|
||||
|
||||
.htags: *.h
|
||||
-htags $?
|
||||
|
||||
retags:
|
||||
-rm -f .tags .htags
|
||||
ctags -f .tags `find $(SDKSRC) -name '*.h'`
|
||||
ctags -f .tags -a `find $(METADIR) -name old -prune -o -name '*.h' -print`
|
||||
ctags -f .tags -a $(SRCFILES)
|
||||
htags -R $(SDKSRC)
|
||||
htags `find $(METADIR) -name old -prune -o -name '*.h' -print`
|
||||
htags *.h
|
||||
|
||||
clean: clean_$(OSTARGET)
|
||||
|
||||
clean_linux:
|
||||
test -n "$(OBJDIR_LINUX)"
|
||||
-rm -f $(OBJDIR_LINUX)/*
|
||||
|
||||
clean_win32:
|
||||
test -n "$(OBJDIR_WIN)"
|
||||
-rm -f $(OBJDIR_WIN)/*
|
||||
|
||||
cleanall_linux:
|
||||
$(MAKE) clean_linux
|
||||
$(MAKE) clean_linux OPT=opt
|
||||
$(MAKE) clean_linux TARGET=amd64
|
||||
$(MAKE) clean_linux TARGET=amd64 OPT=opt
|
||||
|
||||
cleanall_win32:
|
||||
$(MAKE) clean_win32
|
||||
$(MAKE) clean_win32 OPT=opt
|
||||
|
||||
cleanall: cleanall_linux cleanall_win32
|
||||
|
||||
dll_linux dll_win32:
|
||||
$(MAKE) do_$@
|
||||
$(MAKE) do_$@ OPT=opt
|
||||
|
||||
do_dll_linux: $(DLLS_DIR) $(DLLS_DIR)/$(LIBFILE_LINUX)
|
||||
do_dll_win32: $(DLLS_DIR) $(DLLS_DIR)/$(LIBFILE_WIN)
|
||||
|
||||
$(DLLS_DIR):
|
||||
mkdir $(DLLS_DIR)
|
||||
|
||||
$(DLLS_DIR)/$(LIBFILE_LINUX): $(TARGET_LINUX)
|
||||
$(INSTALL) $+ $@
|
||||
|
||||
$(DLLS_DIR)/$(LIBFILE_WIN): $(TARGET_WIN)
|
||||
$(INSTALL) $+ $@
|
||||
|
||||
dlls: dll_linux dll_win32
|
||||
rmdlls:
|
||||
-rm -f ../dlls/*.* ../dlls/debug/*.*
|
||||
|
||||
spotless: cleanall
|
||||
-rmdir $(OBJDIR_LINUX) $(OBJDIR_WIN)
|
||||
# -rm -f .snap $(GENERATED)
|
||||
|
||||
distclean: spotless
|
||||
|
||||
install: $(INST_DIR)/$(LIBFILE)
|
||||
test: $(TEST_DIR)/$(LIBFILE)
|
||||
test_opt:
|
||||
$(MAKE) test OPT=opt
|
||||
|
||||
$(INST_DIR)/$(LIBFILE) $(TEST_DIR)/$(LIBFILE): $(TARGET_FILE)
|
||||
$(INSTALL) $< $@
|
||||
|
||||
tst: $(TST_DIR)/$(LIBFILE_WIN)
|
||||
|
||||
$(TST_DIR)/$(LIBFILE_WIN): $(TARGET_WIN)
|
||||
cp $< $@
|
||||
|
||||
snap: .snap
|
||||
|
||||
.snap: $(FILES_ALL)
|
||||
mkdir -p snapshots
|
||||
tar zcvf snapshots/`date '+%m%d-%H%M'`.tgz $(FILES_ALL)
|
||||
touch .snap
|
||||
|
||||
depend: $(OBJDIR)/Rules.depend
|
||||
|
||||
$(OBJDIR)/Rules.depend: Makefile $(SRCFILES) $(OBJDIR)
|
||||
$(CC_DEP) -MM $(INCLUDEDIRS) $(SRCFILES) | sed "s;\(^[^ ]*\):\(.*\);$(OBJDIR)/\1: Makefile Config.mak \2;" > $@
|
||||
|
||||
include $(OBJDIR)/Rules.depend
|
||||
@@ -1,690 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
||||
*
|
||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h> // offsetof
|
||||
#include <extdll.h>
|
||||
|
||||
#include "ret_type.h"
|
||||
#include "types_meta.h"
|
||||
#include "api_info.h"
|
||||
#include "api_hook.h"
|
||||
#include "mplugin.h"
|
||||
#include "metamod.h"
|
||||
#include "osdep.h" //unlikely
|
||||
|
||||
// getting pointer with table index is faster than with if-else
|
||||
static const void ** api_tables[3] = {
|
||||
(const void**)&Engine.funcs,
|
||||
(const void**)&GameDLL.funcs.dllapi_table,
|
||||
(const void**)&GameDLL.funcs.newapi_table
|
||||
};
|
||||
|
||||
static const void ** api_info_tables[3] = {
|
||||
(const void**)&engine_info,
|
||||
(const void**)&dllapi_info,
|
||||
(const void**)&newapi_info
|
||||
};
|
||||
|
||||
// Safety check for metamod-bot-plugin bugfix.
|
||||
// engine_api->pfnRunPlayerMove calls dllapi-functions before it returns.
|
||||
// This causes problems with bots running as metamod plugins, because
|
||||
// metamod assumed that PublicMetaGlobals is free to be used.
|
||||
// With call_count we can fix this by backuping up PublicMetaGlobals if
|
||||
// it's already being used.
|
||||
static unsigned int call_count = 0;
|
||||
|
||||
// get function pointer from api table by function pointer offset
|
||||
inline void * DLLINTERNAL get_api_function(const void * api_table, unsigned int func_offset) {
|
||||
return(*(void**)((unsigned long)api_table + func_offset));
|
||||
}
|
||||
|
||||
// get data pointer from api_info table by function offset
|
||||
inline const api_info_t * DLLINTERNAL get_api_info(enum_api_t api, unsigned int api_info_offset) {
|
||||
return((const api_info_t *)((unsigned long)api_info_tables[api] + api_info_offset));
|
||||
}
|
||||
|
||||
// simplified 'void' version of main hook function
|
||||
void DLLINTERNAL main_hook_function_void(unsigned int api_info_offset, enum_api_t api, unsigned int func_offset, const void * packed_args) {
|
||||
const api_info_t *api_info;
|
||||
int i;
|
||||
META_RES mres, status, prev_mres;
|
||||
MPlugin *iplug;
|
||||
void *pfn_routine;
|
||||
int loglevel;
|
||||
const void *api_table;
|
||||
meta_globals_t backup_meta_globals[1];
|
||||
|
||||
//passing offset from api wrapper function makes code faster/smaller
|
||||
api_info = get_api_info(api, api_info_offset);
|
||||
|
||||
//Fix bug with metamod-bot-plugins.
|
||||
if(unlikely(call_count++>0)) {
|
||||
//Backup PublicMetaGlobals.
|
||||
backup_meta_globals[0] = PublicMetaGlobals;
|
||||
}
|
||||
|
||||
//Setup
|
||||
loglevel=api_info->loglevel;
|
||||
mres=MRES_UNSET;
|
||||
status=MRES_UNSET;
|
||||
prev_mres=MRES_UNSET;
|
||||
pfn_routine=NULL;
|
||||
|
||||
//Pre plugin functions
|
||||
prev_mres=MRES_UNSET;
|
||||
for(i=0; likely(i < Plugins->endlist); i++) {
|
||||
iplug=&Plugins->plist[i];
|
||||
|
||||
if(unlikely(iplug->status != PL_RUNNING))
|
||||
continue;
|
||||
|
||||
api_table = iplug->get_api_table(api);
|
||||
if(likely(!api_table)) {
|
||||
//plugin doesn't provide this api table
|
||||
continue;
|
||||
}
|
||||
|
||||
pfn_routine=get_api_function(api_table, func_offset);
|
||||
if(likely(!pfn_routine)) {
|
||||
//plugin doesn't provide this function
|
||||
continue;
|
||||
}
|
||||
|
||||
// initialize PublicMetaGlobals
|
||||
PublicMetaGlobals.mres = MRES_UNSET;
|
||||
PublicMetaGlobals.prev_mres = prev_mres;
|
||||
PublicMetaGlobals.status = status;
|
||||
|
||||
// call plugin
|
||||
META_DEBUG(loglevel, ("Calling %s:%s()", iplug->file, api_info->name));
|
||||
api_info->api_caller(pfn_routine, packed_args);
|
||||
API_UNPAUSE_TSC_TRACKING();
|
||||
|
||||
// plugin's result code
|
||||
mres=PublicMetaGlobals.mres;
|
||||
if(unlikely(mres > status))
|
||||
status = mres;
|
||||
|
||||
// save this for successive plugins to see
|
||||
prev_mres = mres;
|
||||
|
||||
if(unlikely(mres==MRES_UNSET))
|
||||
META_WARNING("Plugin didn't set meta_result: %s:%s()", iplug->file, api_info->name);
|
||||
}
|
||||
|
||||
call_count--;
|
||||
|
||||
//Api call
|
||||
if(likely(status!=MRES_SUPERCEDE)) {
|
||||
//get api table
|
||||
api_table = *api_tables[api];
|
||||
|
||||
if(likely(api_table)) {
|
||||
pfn_routine = get_api_function(api_table, func_offset);
|
||||
if(likely(pfn_routine)) {
|
||||
META_DEBUG(loglevel, ("Calling %s:%s()", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
||||
api_info->api_caller(pfn_routine, packed_args);
|
||||
API_UNPAUSE_TSC_TRACKING();
|
||||
} else {
|
||||
// don't complain for NULL routines in NEW_DLL_FUNCTIONS
|
||||
if(unlikely(api != e_api_newapi))
|
||||
META_WARNING("Couldn't find api call: %s:%s", (api==e_api_engine)?"engine":GameDLL.file, api_info->name);
|
||||
status=MRES_UNSET;
|
||||
}
|
||||
} else {
|
||||
// don't complain for NULL NEW_DLL_FUNCTIONS-table
|
||||
if(unlikely(api != e_api_newapi))
|
||||
META_DEBUG(loglevel, ("No api table defined for api call: %s:%s", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
||||
status=MRES_UNSET;
|
||||
}
|
||||
} else
|
||||
META_DEBUG(loglevel, ("Skipped (supercede) %s:%s()", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
||||
|
||||
call_count++;
|
||||
|
||||
//Post plugin functions
|
||||
prev_mres=MRES_UNSET;
|
||||
for(i=0; likely(i < Plugins->endlist); i++) {
|
||||
iplug=&Plugins->plist[i];
|
||||
|
||||
if(unlikely(iplug->status != PL_RUNNING))
|
||||
continue;
|
||||
|
||||
api_table = iplug->get_api_post_table(api);
|
||||
if(likely(!api_table)) {
|
||||
//plugin doesn't provide this api table
|
||||
continue;
|
||||
}
|
||||
|
||||
pfn_routine=get_api_function(api_table, func_offset);
|
||||
if(likely(!pfn_routine)) {
|
||||
//plugin doesn't provide this function
|
||||
continue;
|
||||
}
|
||||
|
||||
// initialize PublicMetaGlobals
|
||||
PublicMetaGlobals.mres = MRES_UNSET;
|
||||
PublicMetaGlobals.prev_mres = prev_mres;
|
||||
PublicMetaGlobals.status = status;
|
||||
|
||||
// call plugin
|
||||
META_DEBUG(loglevel, ("Calling %s:%s_Post()", iplug->file, api_info->name));
|
||||
api_info->api_caller(pfn_routine, packed_args);
|
||||
API_UNPAUSE_TSC_TRACKING();
|
||||
|
||||
// plugin's result code
|
||||
mres=PublicMetaGlobals.mres;
|
||||
if(unlikely(mres > status))
|
||||
status = mres;
|
||||
|
||||
// save this for successive plugins to see
|
||||
prev_mres = mres;
|
||||
|
||||
if(unlikely(mres==MRES_UNSET))
|
||||
META_WARNING("Plugin didn't set meta_result: %s:%s_Post()", iplug->file, api_info->name);
|
||||
else if(unlikely(mres==MRES_SUPERCEDE))
|
||||
META_WARNING("MRES_SUPERCEDE not valid in Post functions: %s:%s_Post()", iplug->file, api_info->name);
|
||||
}
|
||||
|
||||
if(unlikely(--call_count>0)) {
|
||||
//Restore backup
|
||||
PublicMetaGlobals = backup_meta_globals[0];
|
||||
}
|
||||
}
|
||||
|
||||
// full return typed version of main hook function
|
||||
void * DLLINTERNAL main_hook_function(const class_ret_t ret_init, unsigned int api_info_offset, enum_api_t api, unsigned int func_offset, const void * packed_args) {
|
||||
const api_info_t *api_info;
|
||||
int i;
|
||||
META_RES mres, status, prev_mres;
|
||||
MPlugin *iplug;
|
||||
void *pfn_routine;
|
||||
int loglevel;
|
||||
const void *api_table;
|
||||
meta_globals_t backup_meta_globals[1];
|
||||
|
||||
//passing offset from api wrapper function makes code faster/smaller
|
||||
api_info = get_api_info(api, api_info_offset);
|
||||
|
||||
//Fix bug with metamod-bot-plugins.
|
||||
if(unlikely(call_count++>0)) {
|
||||
//Backup PublicMetaGlobals.
|
||||
backup_meta_globals[0] = PublicMetaGlobals;
|
||||
}
|
||||
|
||||
//Return class setup
|
||||
class_ret_t dllret=ret_init;
|
||||
class_ret_t override_ret=ret_init;
|
||||
class_ret_t pub_override_ret=ret_init;
|
||||
class_ret_t orig_ret=ret_init;
|
||||
class_ret_t pub_orig_ret=ret_init;
|
||||
|
||||
//Setup
|
||||
loglevel=api_info->loglevel;
|
||||
mres=MRES_UNSET;
|
||||
status=MRES_UNSET;
|
||||
prev_mres=MRES_UNSET;
|
||||
pfn_routine=NULL;
|
||||
|
||||
//Pre plugin functions
|
||||
prev_mres=MRES_UNSET;
|
||||
for(i=0; likely(i < Plugins->endlist); i++) {
|
||||
iplug=&Plugins->plist[i];
|
||||
|
||||
if(unlikely(iplug->status != PL_RUNNING))
|
||||
continue;
|
||||
|
||||
api_table = iplug->get_api_table(api);
|
||||
if(likely(!api_table)) {
|
||||
//plugin doesn't provide this api table
|
||||
continue;
|
||||
}
|
||||
|
||||
pfn_routine=get_api_function(api_table, func_offset);
|
||||
if(likely(!pfn_routine)) {
|
||||
//plugin doesn't provide this function
|
||||
continue;
|
||||
}
|
||||
|
||||
// initialize PublicMetaGlobals
|
||||
PublicMetaGlobals.mres = MRES_UNSET;
|
||||
PublicMetaGlobals.prev_mres = prev_mres;
|
||||
PublicMetaGlobals.status = status;
|
||||
pub_orig_ret = orig_ret;
|
||||
PublicMetaGlobals.orig_ret = pub_orig_ret.getptr();
|
||||
if(unlikely(status==MRES_SUPERCEDE)) {
|
||||
pub_override_ret = override_ret;
|
||||
PublicMetaGlobals.override_ret = pub_override_ret.getptr();
|
||||
}
|
||||
|
||||
// call plugin
|
||||
META_DEBUG(loglevel, ("Calling %s:%s()", iplug->file, api_info->name));
|
||||
dllret = class_ret_t(api_info->api_caller(pfn_routine, packed_args));
|
||||
API_UNPAUSE_TSC_TRACKING();
|
||||
|
||||
// plugin's result code
|
||||
mres=PublicMetaGlobals.mres;
|
||||
if(unlikely(mres > status))
|
||||
status = mres;
|
||||
|
||||
// save this for successive plugins to see
|
||||
prev_mres = mres;
|
||||
|
||||
if(unlikely(mres==MRES_SUPERCEDE)) {
|
||||
pub_override_ret = dllret;
|
||||
override_ret = dllret;
|
||||
}
|
||||
else if(unlikely(mres==MRES_UNSET)) {
|
||||
META_WARNING("Plugin didn't set meta_result: %s:%s()", iplug->file, api_info->name);
|
||||
}
|
||||
}
|
||||
|
||||
call_count--;
|
||||
|
||||
//Api call
|
||||
if(likely(status!=MRES_SUPERCEDE)) {
|
||||
//get api table
|
||||
api_table = *api_tables[api];
|
||||
|
||||
if(likely(api_table)) {
|
||||
pfn_routine = get_api_function(api_table, func_offset);
|
||||
if(likely(pfn_routine)) {
|
||||
META_DEBUG(loglevel, ("Calling %s:%s()", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
||||
dllret = class_ret_t(api_info->api_caller(pfn_routine, packed_args));
|
||||
API_UNPAUSE_TSC_TRACKING();
|
||||
orig_ret = dllret;
|
||||
} else {
|
||||
// don't complain for NULL routines in NEW_DLL_FUNCTIONS
|
||||
if(unlikely(api != e_api_newapi))
|
||||
META_WARNING("Couldn't find api call: %s:%s", (api==e_api_engine)?"engine":GameDLL.file, api_info->name);
|
||||
status=MRES_UNSET;
|
||||
}
|
||||
} else {
|
||||
// don't complain for NULL NEW_DLL_FUNCTIONS-table
|
||||
if(unlikely(api != e_api_newapi))
|
||||
META_DEBUG(loglevel, ("No api table defined for api call: %s:%s", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
||||
status=MRES_UNSET;
|
||||
}
|
||||
} else {
|
||||
META_DEBUG(loglevel, ("Skipped (supercede) %s:%s()", (api==e_api_engine)?"engine":GameDLL.file, api_info->name));
|
||||
orig_ret = override_ret;
|
||||
pub_orig_ret = override_ret;
|
||||
PublicMetaGlobals.orig_ret = pub_orig_ret.getptr();
|
||||
}
|
||||
|
||||
call_count++;
|
||||
|
||||
//Pre plugin functions
|
||||
prev_mres=MRES_UNSET;
|
||||
for(i=0; likely(i < Plugins->endlist); i++) {
|
||||
iplug=&Plugins->plist[i];
|
||||
|
||||
if(unlikely(iplug->status != PL_RUNNING))
|
||||
continue;
|
||||
|
||||
api_table = iplug->get_api_post_table(api);
|
||||
if(likely(!api_table)) {
|
||||
//plugin doesn't provide this api table
|
||||
continue;
|
||||
}
|
||||
|
||||
pfn_routine=get_api_function(api_table, func_offset);
|
||||
if(likely(!pfn_routine)) {
|
||||
//plugin doesn't provide this function
|
||||
continue;
|
||||
}
|
||||
|
||||
// initialize PublicMetaGlobals
|
||||
PublicMetaGlobals.mres = MRES_UNSET;
|
||||
PublicMetaGlobals.prev_mres = prev_mres;
|
||||
PublicMetaGlobals.status = status;
|
||||
pub_orig_ret = orig_ret;
|
||||
PublicMetaGlobals.orig_ret = pub_orig_ret.getptr();
|
||||
if(unlikely(status==MRES_OVERRIDE)) {
|
||||
pub_override_ret = override_ret;
|
||||
PublicMetaGlobals.override_ret = pub_override_ret.getptr();
|
||||
}
|
||||
|
||||
// call plugin
|
||||
META_DEBUG(loglevel, ("Calling %s:%s_Post()", iplug->file, api_info->name));
|
||||
dllret = class_ret_t(api_info->api_caller(pfn_routine, packed_args));
|
||||
API_UNPAUSE_TSC_TRACKING();
|
||||
|
||||
// plugin's result code
|
||||
mres=PublicMetaGlobals.mres;
|
||||
if(unlikely(mres > status))
|
||||
status = mres;
|
||||
|
||||
// save this for successive plugins to see
|
||||
prev_mres = mres;
|
||||
|
||||
if(unlikely(mres==MRES_OVERRIDE)) {
|
||||
pub_override_ret = dllret;
|
||||
override_ret = dllret;
|
||||
}
|
||||
else if(unlikely(mres==MRES_UNSET)) {
|
||||
META_WARNING("Plugin didn't set meta_result: %s:%s_Post()", iplug->file, api_info->name);
|
||||
}
|
||||
else if(unlikely(mres==MRES_SUPERCEDE)) {
|
||||
META_WARNING("MRES_SUPERCEDE not valid in Post functions: %s:%s_Post()", iplug->file, api_info->name);
|
||||
}
|
||||
}
|
||||
|
||||
if(unlikely(--call_count>0)) {
|
||||
//Restore backup
|
||||
PublicMetaGlobals = backup_meta_globals[0];
|
||||
}
|
||||
|
||||
//return value is passed through ret_init!
|
||||
if(likely(status!=MRES_OVERRIDE)) {
|
||||
return(*(void**)orig_ret.getptr());
|
||||
} else {
|
||||
META_DEBUG(loglevel, ("Returning (override) %s()", api_info->name));
|
||||
return(*(void**)override_ret.getptr());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Macros for creating api caller functions
|
||||
//
|
||||
#define BEGIN_API_CALLER_FUNC(ret_type, args_type_code) \
|
||||
void * DLLINTERNAL _COMBINE4(api_caller_, ret_type, _args_, args_type_code)(const void * func, const void * packed_args) { \
|
||||
_COMBINE2(pack_args_type_, args_type_code) * p ATTRIBUTE(unused)= (_COMBINE2(pack_args_type_, args_type_code) *)packed_args;
|
||||
#define END_API_CALLER_FUNC(ret_t, args_t, args) \
|
||||
API_PAUSE_TSC_TRACKING(); \
|
||||
return(*(void **)class_ret_t((*(( ret_t (*) args_t )func)) args).getptr()); \
|
||||
}
|
||||
#define END_API_CALLER_FUNC_void(args_t, args) \
|
||||
API_PAUSE_TSC_TRACKING(); \
|
||||
return((*(( void* (*) args_t )func)) args); \
|
||||
}
|
||||
|
||||
//
|
||||
// API function callers.
|
||||
//
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, ipV)
|
||||
END_API_CALLER_FUNC_void( (int, const void*, ...), (p->i1, p->p1, p->str) )
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2pV)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, ...), (p->p1, p->p2, p->str) )
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, void)
|
||||
END_API_CALLER_FUNC_void( (void), () )
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, void)
|
||||
END_API_CALLER_FUNC(void*, (void), () )
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, void)
|
||||
END_API_CALLER_FUNC(int, (void), () )
|
||||
|
||||
BEGIN_API_CALLER_FUNC(float, void)
|
||||
END_API_CALLER_FUNC(float, (void), () )
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(float, 2f)
|
||||
END_API_CALLER_FUNC( float, (float, float), (p->f1, p->f2) )
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2i)
|
||||
END_API_CALLER_FUNC_void( (int, int), (p->i1, p->i2) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, 2i)
|
||||
END_API_CALLER_FUNC(int, (int, int), (p->i1, p->i2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2i2p)
|
||||
END_API_CALLER_FUNC_void( (int, int, const void*, const void*), (p->i1, p->i2, p->p1, p->p2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2i2pi2p)
|
||||
END_API_CALLER_FUNC_void( (int, int, const void*, const void*, int, const void*, const void*), (p->i1, p->i2, p->p1, p->p2, p->i3, p->p3, p->p4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2p)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*), (p->p1, p->p2) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, 2p)
|
||||
END_API_CALLER_FUNC(void*, (const void*, const void*), (p->p1, p->p2) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, 2p)
|
||||
END_API_CALLER_FUNC(int, (const void*, const void*), (p->p1, p->p2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2p2f)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, float, float), (p->p1, p->p2, p->f1, p->f2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2p2i2p)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, int, int, const void*, const void*), (p->p1, p->p2, p->i1, p->i2, p->p3, p->p4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2p3fus2uc)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, float, float, float, unsigned short, unsigned char, unsigned char), (p->p1, p->p2, p->f1, p->f2, p->f3, p->us1, p->uc1, p->uc2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(ptr, 2pf)
|
||||
END_API_CALLER_FUNC(void*, (const void*, const void*, float), (p->p1, p->p2, p->f1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2pfi)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, float, int), (p->p1, p->p2, p->f1, p->i1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2pi)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, int), (p->p1, p->p2, p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, 2pi)
|
||||
END_API_CALLER_FUNC(int, (const void*, const void*, int), (p->p1, p->p2, p->i1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2pui)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, unsigned int), (p->p1, p->p2, p->ui1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2pi2p)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, int, const void*, const void*), (p->p1, p->p2, p->i1, p->p3, p->p4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 2pif2p)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, int, float, const void*, const void*), (p->p1, p->p2, p->i1, p->f1, p->p3, p->p4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(int, 3i)
|
||||
END_API_CALLER_FUNC(int, (int, int, int), (p->i1, p->i2, p->i3) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 3p)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, const void*), (p->p1, p->p2, p->p3) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, 3p)
|
||||
END_API_CALLER_FUNC(void*, (const void*, const void*, const void*), (p->p1, p->p2, p->p3) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, 3p)
|
||||
END_API_CALLER_FUNC(int, (const void*, const void*, const void*), (p->p1, p->p2, p->p3) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 3p2f2i)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, const void*, float, float, int, int), (p->p1, p->p2, p->p3, p->f1, p->f2, p->i1, p->i2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(int, 3pi2p)
|
||||
END_API_CALLER_FUNC(int, (const void*, const void*, const void*, int, const void*, const void*), (p->p1, p->p2, p->p3, p->i1, p->p4, p->p5) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 4p)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, const void*, const void*), (p->p1, p->p2, p->p3, p->p4) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, 4p)
|
||||
END_API_CALLER_FUNC(int, (const void*, const void*, const void*, const void*), (p->p1, p->p2, p->p3, p->p4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, 4pi)
|
||||
END_API_CALLER_FUNC_void( (const void*, const void*, const void*, const void*, int), (p->p1, p->p2, p->p3, p->p4, p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, 4pi)
|
||||
END_API_CALLER_FUNC(int, (const void*, const void*, const void*, const void*, int), (p->p1, p->p2, p->p3, p->p4, p->i1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, f)
|
||||
END_API_CALLER_FUNC_void( (float), (p->f1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, i)
|
||||
END_API_CALLER_FUNC_void( (int), (p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, i)
|
||||
END_API_CALLER_FUNC(int, (int), (p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, i)
|
||||
END_API_CALLER_FUNC(void*, (int), (p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(uint, ui)
|
||||
END_API_CALLER_FUNC(unsigned int, (unsigned int), (p->ui1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, ui)
|
||||
END_API_CALLER_FUNC(void*, (unsigned int), (p->ui1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(ulong, ul)
|
||||
END_API_CALLER_FUNC(unsigned long, (unsigned long), (p->ul1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, i2p)
|
||||
END_API_CALLER_FUNC_void( (int, const void*, const void*), (p->i1, p->p1, p->p2) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, i2p)
|
||||
END_API_CALLER_FUNC(int, (int, const void*, const void*), (p->i1, p->p1, p->p2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, i3p)
|
||||
END_API_CALLER_FUNC_void( (int, const void*, const void*, const void*), (p->i1, p->p1, p->p2, p->p3) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, ip)
|
||||
END_API_CALLER_FUNC_void( (int, const void*), (p->i1, p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ushort, ip)
|
||||
END_API_CALLER_FUNC( unsigned short, (int, const void*), (p->i1, p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, ip)
|
||||
END_API_CALLER_FUNC( int, (int, const void*), (p->i1, p->p1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, ipusf2p2f4i)
|
||||
END_API_CALLER_FUNC_void( (int, const void*, unsigned short, float, const void*, const void*, float, float, int, int, int, int), (p->i1, p->p1, p->us1, p->f1, p->p2, p->p3, p->f2, p->f3, p->i2, p->i3, p->i4, p->i5) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, p)
|
||||
END_API_CALLER_FUNC_void( (const void*), (p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, p)
|
||||
END_API_CALLER_FUNC(void*, (const void*), (p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(char, p)
|
||||
END_API_CALLER_FUNC(char, (const void*), (p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, p)
|
||||
END_API_CALLER_FUNC(int, (const void*), (p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(uint, p)
|
||||
END_API_CALLER_FUNC(unsigned int, (const void*), (p->p1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(float, p)
|
||||
END_API_CALLER_FUNC(float, (const void*), (p->p1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, p2f)
|
||||
END_API_CALLER_FUNC_void( (const void*, float, float), (p->p1, p->f1, p->f2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(int, p2fi)
|
||||
END_API_CALLER_FUNC(int, (const void*, float, float, int), (p->p1, p->f1, p->f2, p->i1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, p2i)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, int), (p->p1, p->i1, p->i2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, p3i)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, int, int), (p->p1, p->i1, p->i2, p->i3) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, p4i)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, int, int, int), (p->p1, p->i1, p->i2, p->i3, p->i4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, puc)
|
||||
END_API_CALLER_FUNC_void( (const void*, unsigned char), (p->p1, p->uc1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pf)
|
||||
END_API_CALLER_FUNC_void( (const void*, float), (p->p1, p->f1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pfp)
|
||||
END_API_CALLER_FUNC_void( (const void*, float, const void*), (p->p1, p->f1, p->p2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pi)
|
||||
END_API_CALLER_FUNC_void( (const void*, int), (p->p1, p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, pi)
|
||||
END_API_CALLER_FUNC(void*, (const void*, int), (p->p1, p->i1) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(int, pi)
|
||||
END_API_CALLER_FUNC(int, (const void*, int), (p->p1, p->i1) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pi2p)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, const void*, const void*), (p->p1, p->i1, p->p2, p->p3) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(int, pi2p2ip)
|
||||
END_API_CALLER_FUNC(int, (const void*, int, const void*, const void*, int, int, const void*), (p->p1, p->i1, p->p2, p->p3, p->i2, p->i3, p->p4) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pip)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, const void*), (p->p1, p->i1, p->p2) );
|
||||
|
||||
BEGIN_API_CALLER_FUNC(ptr, pip)
|
||||
END_API_CALLER_FUNC(void*, (const void*, int, const void*), (p->p1, p->i1, p->p2) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pip2f2i)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, const void*, float, float, int, int), (p->p1, p->i1, p->p2, p->f1, p->f2, p->i2, p->i3) );
|
||||
|
||||
//-
|
||||
BEGIN_API_CALLER_FUNC(void, pip2f4i2p)
|
||||
END_API_CALLER_FUNC_void( (const void*, int, const void*, float, float, int, int, int, int, const void*, const void*), (p->p1, p->i1, p->p2, p->f1, p->f2, p->i2, p->i3, p->i4, p->i5, p->p3, p->p4) );
|
||||
@@ -1,275 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// api_info.cpp - info for api routines
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "api_info.h" // me
|
||||
#include "api_hook.h"
|
||||
|
||||
// trace flag, loglevel, name
|
||||
const dllapi_info_t dllapi_info = {
|
||||
{ mFALSE, 3, api_caller_void_args_void, "GameDLLInit" }, // pfnGameInit
|
||||
{ mFALSE, 10, api_caller_int_args_p, "DispatchSpawn" }, // pfnSpawn
|
||||
{ mFALSE, 16, api_caller_void_args_p, "DispatchThink" }, // pfnThink
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "DispatchUse" }, // pfnUse
|
||||
{ mFALSE, 11, api_caller_void_args_2p, "DispatchTouch" }, // pfnTouch
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "DispatchBlocked" }, // pfnBlocked
|
||||
{ mFALSE, 10, api_caller_void_args_2p, "DispatchKeyValue" }, // pfnKeyValue
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "DispatchSave" }, // pfnSave
|
||||
{ mFALSE, 9, api_caller_int_args_2pi, "DispatchRestore" }, // pfnRestore
|
||||
{ mFALSE, 20, api_caller_void_args_p, "DispatchObjectCollsionBox" }, // pfnSetAbsBox
|
||||
{ mFALSE, 9, api_caller_void_args_4pi, "SaveWriteFields" }, // pfnSaveWriteFields
|
||||
{ mFALSE, 9, api_caller_void_args_4pi, "SaveReadFields" }, // pfnSaveReadFields
|
||||
{ mFALSE, 9, api_caller_void_args_p, "SaveGlobalState" }, // pfnSaveGlobalState
|
||||
{ mFALSE, 9, api_caller_void_args_p, "RestoreGlobalState" }, // pfnRestoreGlobalState
|
||||
{ mFALSE, 9, api_caller_void_args_void, "ResetGlobalState" }, // pfnResetGlobalState
|
||||
{ mFALSE, 3, api_caller_int_args_4p, "ClientConnect" }, // pfnClientConnect
|
||||
{ mFALSE, 3, api_caller_void_args_p, "ClientDisconnect" }, // pfnClientDisconnect
|
||||
{ mFALSE, 3, api_caller_void_args_p, "ClientKill" }, // pfnClientKill
|
||||
{ mFALSE, 3, api_caller_void_args_p, "ClientPutInServer" }, // pfnClientPutInServer
|
||||
{ mFALSE, 9, api_caller_void_args_p, "ClientCommand" }, // pfnClientCommand
|
||||
{ mFALSE, 11, api_caller_void_args_2p, "ClientUserInfoChanged" }, // pfnClientUserInfoChanged
|
||||
{ mFALSE, 3, api_caller_void_args_p2i, "ServerActivate" }, // pfnServerActivate
|
||||
{ mFALSE, 3, api_caller_void_args_void, "ServerDeactivate" }, // pfnServerDeactivate
|
||||
{ mFALSE, 14, api_caller_void_args_p, "PlayerPreThink" }, // pfnPlayerPreThink
|
||||
{ mFALSE, 14, api_caller_void_args_p, "PlayerPostThink" }, // pfnPlayerPostThink
|
||||
{ mFALSE, 18, api_caller_void_args_void, "StartFrame" }, // pfnStartFrame
|
||||
{ mFALSE, 9, api_caller_void_args_void, "ParmsNewLevel" }, // pfnParmsNewLevel
|
||||
{ mFALSE, 9, api_caller_void_args_void, "ParmsChangeLevel" }, // pfnParmsChangeLevel
|
||||
{ mFALSE, 9, api_caller_ptr_args_void, "GetGameDescription" }, // pfnGetGameDescription
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "PlayerCustomization" }, // pfnPlayerCustomization
|
||||
{ mFALSE, 9, api_caller_void_args_p, "SpectatorConnect" }, // pfnSpectatorConnect
|
||||
{ mFALSE, 9, api_caller_void_args_p, "SpectatorDisconnect" }, // pfnSpectatorDisconnect
|
||||
{ mFALSE, 9, api_caller_void_args_p, "SpectatorThink" }, // pfnSpectatorThink
|
||||
{ mFALSE, 3, api_caller_void_args_p, "Sys_Error" }, // pfnSys_Error
|
||||
{ mFALSE, 13, api_caller_void_args_pi, "PM_Move" }, // pfnPM_Move
|
||||
{ mFALSE, 9, api_caller_void_args_p, "PM_Init" }, // pfnPM_Init
|
||||
{ mFALSE, 9, api_caller_char_args_p, "PM_FindTextureType" }, // pfnPM_FindTextureType
|
||||
{ mFALSE, 12, api_caller_void_args_4p, "SetupVisibility" }, // pfnSetupVisibility
|
||||
{ mFALSE, 12, api_caller_void_args_pip, "UpdateClientData" }, // pfnUpdateClientData
|
||||
{ mFALSE, 16, api_caller_int_args_pi2p2ip, "AddToFullPack" }, // pfnAddToFullPack
|
||||
{ mFALSE, 9, api_caller_void_args_2i2pi2p, "CreateBaseline" }, // pfnCreateBaseline
|
||||
{ mFALSE, 9, api_caller_void_args_void, "RegisterEncoders" }, // pfnRegisterEncoders
|
||||
{ mFALSE, 9, api_caller_int_args_2p, "GetWeaponData" }, // pfnGetWeaponData
|
||||
{ mFALSE, 15, api_caller_void_args_2pui, "CmdStart" }, // pfnCmdStart
|
||||
{ mFALSE, 15, api_caller_void_args_p, "CmdEnd" }, // pfnCmdEnd
|
||||
{ mFALSE, 9, api_caller_int_args_4p, "ConnectionlessPacket" }, // pfnConnectionlessPacket
|
||||
{ mFALSE, 9, api_caller_int_args_i2p, "GetHullBounds" }, // pfnGetHullBounds
|
||||
{ mFALSE, 9, api_caller_void_args_void, "CreateInstancedBaselines" }, // pfnCreateInstancedBaselines
|
||||
{ mFALSE, 3, api_caller_int_args_3p, "InconsistentFile" }, // pfnInconsistentFile
|
||||
{ mFALSE, 20, api_caller_int_args_void, "AllowLagCompensation" }, // pfnAllowLagCompensation
|
||||
{ mFALSE, 0, NULL, NULL },
|
||||
};
|
||||
|
||||
const newapi_info_t newapi_info = {
|
||||
{ mFALSE, 16, api_caller_void_args_p, "OnFreeEntPrivateData" }, // pfnOnFreeEntPrivateData
|
||||
{ mFALSE, 3, api_caller_void_args_void, "GameShutdown" }, // pfnGameShutdown
|
||||
{ mFALSE, 14, api_caller_int_args_2p, "ShouldCollide" }, // pfnShouldCollide
|
||||
// Added 2005/08/11 (no SDK update):
|
||||
{ mFALSE, 3, api_caller_void_args_2p, "CvarValue" }, // pfnCvarValue
|
||||
// Added 2005/11/21 (no SDK update):
|
||||
{ mFALSE, 3, api_caller_void_args_pi2p, "CvarValue2" }, // pfnCvarValue2
|
||||
{ mFALSE, 0, NULL, NULL },
|
||||
};
|
||||
|
||||
const engine_info_t engine_info = {
|
||||
{ mFALSE, 13, api_caller_int_args_p, "PrecacheModel" }, // pfnPrecacheModel
|
||||
{ mFALSE, 13, api_caller_int_args_p, "PrecacheSound" }, // pfnPrecacheSound
|
||||
{ mFALSE, 18, api_caller_void_args_2p, "SetModel" }, // pfnSetModel
|
||||
{ mFALSE, 34, api_caller_int_args_p, "ModelIndex" }, // pfnModelIndex
|
||||
{ mFALSE, 10, api_caller_int_args_i, "ModelFrames" }, // pfnModelFrames
|
||||
{ mFALSE, 14, api_caller_void_args_3p, "SetSize" }, // pfnSetSize
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "ChangeLevel" }, // pfnChangeLevel
|
||||
{ mFALSE, 9, api_caller_void_args_p, "GetSpawnParms" }, // pfnGetSpawnParms
|
||||
{ mFALSE, 9, api_caller_void_args_p, "SaveSpawnParms" }, // pfnSaveSpawnParms
|
||||
{ mFALSE, 9, api_caller_float_args_p, "VecToYaw" }, // pfnVecToYaw
|
||||
{ mFALSE, 14, api_caller_void_args_2p, "VecToAngles" }, // pfnVecToAngles
|
||||
{ mFALSE, 9, api_caller_void_args_2pfi, "MoveToOrigin" }, // pfnMoveToOrigin
|
||||
{ mFALSE, 9, api_caller_void_args_p, "ChangeYaw" }, // pfnChangeYaw
|
||||
{ mFALSE, 9, api_caller_void_args_p, "ChangePitch" }, // pfnChangePitch
|
||||
{ mFALSE, 32, api_caller_ptr_args_3p, "FindEntityByString" }, // pfnFindEntityByString
|
||||
{ mFALSE, 9, api_caller_int_args_p, "GetEntityIllum" }, // pfnGetEntityIllum
|
||||
{ mFALSE, 9, api_caller_ptr_args_2pf, "FindEntityInSphere" }, // pfnFindEntityInSphere
|
||||
{ mFALSE, 19, api_caller_ptr_args_p, "FindClientInPVS" }, // pfnFindClientInPVS
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "EntitiesInPVS" }, // pfnEntitiesInPVS
|
||||
{ mFALSE, 40, api_caller_void_args_p, "MakeVectors" }, // pfnMakeVectors
|
||||
{ mFALSE, 9, api_caller_void_args_4p, "AngleVectors" }, // pfnAngleVectors
|
||||
{ mFALSE, 13, api_caller_ptr_args_void, "CreateEntity" }, // pfnCreateEntity
|
||||
{ mFALSE, 13, api_caller_void_args_p, "RemoveEntity" }, // pfnRemoveEntity
|
||||
{ mFALSE, 13, api_caller_ptr_args_i, "CreateNamedEntity" }, // pfnCreateNamedEntity
|
||||
{ mFALSE, 9, api_caller_void_args_p, "MakeStatic" }, // pfnMakeStatic
|
||||
{ mFALSE, 9, api_caller_int_args_p, "EntIsOnFloor" }, // pfnEntIsOnFloor
|
||||
{ mFALSE, 9, api_caller_int_args_p, "DropToFloor" }, // pfnDropToFloor
|
||||
{ mFALSE, 9, api_caller_int_args_p2fi, "WalkMove" }, // pfnWalkMove
|
||||
{ mFALSE, 14, api_caller_void_args_2p, "SetOrigin" }, // pfnSetOrigin
|
||||
{ mFALSE, 12, api_caller_void_args_pip2f2i, "EmitSound" }, // pfnEmitSound
|
||||
{ mFALSE, 12, api_caller_void_args_3p2f2i, "EmitAmbientSound" }, // pfnEmitAmbientSound
|
||||
{ mFALSE, 20, api_caller_void_args_2pi2p, "TraceLine" }, // pfnTraceLine
|
||||
{ mFALSE, 9, api_caller_void_args_3p, "TraceToss" }, // pfnTraceToss
|
||||
{ mFALSE, 9, api_caller_int_args_3pi2p, "TraceMonsterHull" }, // pfnTraceMonsterHull
|
||||
{ mFALSE, 9, api_caller_void_args_2p2i2p, "TraceHull" }, // pfnTraceHull
|
||||
{ mFALSE, 9, api_caller_void_args_2pi2p, "TraceModel" }, // pfnTraceModel
|
||||
{ mFALSE, 15, api_caller_ptr_args_3p, "TraceTexture" }, // pfnTraceTexture // CS: when moving
|
||||
{ mFALSE, 9, api_caller_void_args_2pif2p, "TraceSphere" }, // pfnTraceSphere
|
||||
{ mFALSE, 9, api_caller_void_args_pfp, "GetAimVector" }, // pfnGetAimVector
|
||||
{ mFALSE, 9, api_caller_void_args_p, "ServerCommand" }, // pfnServerCommand
|
||||
{ mFALSE, 9, api_caller_void_args_void, "ServerExecute" }, // pfnServerExecute
|
||||
{ mFALSE, 11, api_caller_void_args_2pV, "engClientCommand" }, // pfnClientCommand // d'oh, ClientCommand in dllapi too
|
||||
{ mFALSE, 9, api_caller_void_args_2p2f, "ParticleEffect" }, // pfnParticleEffect
|
||||
{ mFALSE, 9, api_caller_void_args_ip, "LightStyle" }, // pfnLightStyle
|
||||
{ mFALSE, 9, api_caller_int_args_p, "DecalIndex" }, // pfnDecalIndex
|
||||
{ mFALSE, 15, api_caller_int_args_p, "PointContents" }, // pfnPointContents // CS: when moving
|
||||
{ mFALSE, 22, api_caller_void_args_2i2p, "MessageBegin" }, // pfnMessageBegin
|
||||
{ mFALSE, 22, api_caller_void_args_void, "MessageEnd" }, // pfnMessageEnd
|
||||
{ mFALSE, 30, api_caller_void_args_i, "WriteByte" }, // pfnWriteByte
|
||||
{ mFALSE, 23, api_caller_void_args_i, "WriteChar" }, // pfnWriteChar
|
||||
{ mFALSE, 24, api_caller_void_args_i, "WriteShort" }, // pfnWriteShort
|
||||
{ mFALSE, 23, api_caller_void_args_i, "WriteLong" }, // pfnWriteLong
|
||||
{ mFALSE, 23, api_caller_void_args_f, "WriteAngle" }, // pfnWriteAngle
|
||||
{ mFALSE, 23, api_caller_void_args_f, "WriteCoord" }, // pfnWriteCoord
|
||||
{ mFALSE, 25, api_caller_void_args_p, "WriteString" }, // pfnWriteString
|
||||
{ mFALSE, 23, api_caller_void_args_i, "WriteEntity" }, // pfnWriteEntity
|
||||
{ mFALSE, 9, api_caller_void_args_p, "CVarRegister" }, // pfnCVarRegister
|
||||
{ mFALSE, 21, api_caller_float_args_p, "CVarGetFloat" }, // pfnCVarGetFloat
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "CVarGetString" }, // pfnCVarGetString
|
||||
{ mFALSE, 10, api_caller_void_args_pf, "CVarSetFloat" }, // pfnCVarSetFloat
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "CVarSetString" }, // pfnCVarSetString
|
||||
{ mFALSE, 15, api_caller_void_args_ipV, "AlertMessage" }, // pfnAlertMessage
|
||||
{ mFALSE, 17, api_caller_void_args_2pV, "EngineFprintf" }, // pfnEngineFprintf
|
||||
{ mFALSE, 14, api_caller_ptr_args_pi, "PvAllocEntPrivateData" }, // pfnPvAllocEntPrivateData
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "PvEntPrivateData" }, // pfnPvEntPrivateData
|
||||
{ mFALSE, 9, api_caller_void_args_p, "FreeEntPrivateData" }, // pfnFreeEntPrivateData
|
||||
{ mFALSE, 9, api_caller_ptr_args_i, "SzFromIndex" }, // pfnSzFromIndex
|
||||
{ mFALSE, 10, api_caller_int_args_p, "AllocString" }, // pfnAllocString
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "GetVarsOfEnt" }, // pfnGetVarsOfEnt
|
||||
{ mFALSE, 14, api_caller_ptr_args_i, "PEntityOfEntOffset" }, // pfnPEntityOfEntOffset
|
||||
{ mFALSE, 19, api_caller_int_args_p, "EntOffsetOfPEntity" }, // pfnEntOffsetOfPEntity
|
||||
{ mFALSE, 14, api_caller_int_args_p, "IndexOfEdict" }, // pfnIndexOfEdict
|
||||
{ mFALSE, 17, api_caller_ptr_args_i, "PEntityOfEntIndex" }, // pfnPEntityOfEntIndex
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "FindEntityByVars" }, // pfnFindEntityByVars
|
||||
{ mFALSE, 14, api_caller_ptr_args_p, "GetModelPtr" }, // pfnGetModelPtr
|
||||
{ mFALSE, 9, api_caller_int_args_pi, "RegUserMsg" }, // pfnRegUserMsg
|
||||
{ mFALSE, 9, api_caller_void_args_pf, "AnimationAutomove" }, // pfnAnimationAutomove
|
||||
{ mFALSE, 9, api_caller_void_args_pi2p, "GetBonePosition" }, // pfnGetBonePosition
|
||||
{ mFALSE, 9, api_caller_uint_args_p, "FunctionFromName" }, // pfnFunctionFromName
|
||||
{ mFALSE, 9, api_caller_ptr_args_ui, "NameForFunction" }, // pfnNameForFunction
|
||||
{ mFALSE, 9, api_caller_void_args_pip, "ClientPrintf" }, // pfnClientPrintf
|
||||
{ mFALSE, 9, api_caller_void_args_p, "ServerPrint" }, // pfnServerPrint
|
||||
{ mFALSE, 13, api_caller_ptr_args_void, "Cmd_Args" }, // pfnCmd_Args
|
||||
{ mFALSE, 13, api_caller_ptr_args_i, "Cmd_Argv" }, // pfnCmd_Argv
|
||||
{ mFALSE, 13, api_caller_int_args_void, "Cmd_Argc" }, // pfnCmd_Argc
|
||||
{ mFALSE, 9, api_caller_void_args_pi2p, "GetAttachment" }, // pfnGetAttachment
|
||||
{ mFALSE, 9, api_caller_void_args_p, "CRC32_Init" }, // pfnCRC32_Init
|
||||
{ mFALSE, 9, api_caller_void_args_2pi, "CRC32_ProcessBuffer" }, // pfnCRC32_ProcessBuffer
|
||||
{ mFALSE, 9, api_caller_void_args_puc, "CRC32_ProcessByte" }, // pfnCRC32_ProcessByte
|
||||
{ mFALSE, 9, api_caller_ulong_args_ul, "CRC32_Final" }, // pfnCRC32_Final
|
||||
{ mFALSE, 16, api_caller_int_args_2i, "RandomLong" }, // pfnRandomLong
|
||||
{ mFALSE, 14, api_caller_float_args_2f, "RandomFloat" }, // pfnRandomFloat // CS: when firing
|
||||
{ mFALSE, 14, api_caller_void_args_2p, "SetView" }, // pfnSetView
|
||||
{ mFALSE, 9, api_caller_float_args_void, "Time" }, // pfnTime
|
||||
{ mFALSE, 9, api_caller_void_args_p2f, "CrosshairAngle" }, // pfnCrosshairAngle
|
||||
{ mFALSE, 10, api_caller_ptr_args_2p, "LoadFileForMe" }, // pfnLoadFileForMe
|
||||
{ mFALSE, 10, api_caller_void_args_p, "FreeFile" }, // pfnFreeFile
|
||||
{ mFALSE, 9, api_caller_void_args_p, "EndSection" }, // pfnEndSection
|
||||
{ mFALSE, 9, api_caller_int_args_3p, "CompareFileTime" }, // pfnCompareFileTime
|
||||
{ mFALSE, 9, api_caller_void_args_p, "GetGameDir" }, // pfnGetGameDir
|
||||
{ mFALSE, 9, api_caller_void_args_p, "Cvar_RegisterVariable" }, // pfnCvar_RegisterVariable
|
||||
{ mFALSE, 9, api_caller_void_args_p4i, "FadeClientVolume" }, // pfnFadeClientVolume
|
||||
{ mFALSE, 14, api_caller_void_args_pf, "SetClientMaxspeed" }, // pfnSetClientMaxspeed
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "CreateFakeClient" }, // pfnCreateFakeClient
|
||||
{ mFALSE, 9, api_caller_void_args_2p3fus2uc, "RunPlayerMove" }, // pfnRunPlayerMove
|
||||
{ mFALSE, 9, api_caller_int_args_void, "NumberOfEntities" }, // pfnNumberOfEntities
|
||||
{ mFALSE, 17, api_caller_ptr_args_p, "GetInfoKeyBuffer" }, // pfnGetInfoKeyBuffer
|
||||
{ mFALSE, 13, api_caller_ptr_args_2p, "InfoKeyValue" }, // pfnInfoKeyValue
|
||||
{ mFALSE, 9, api_caller_void_args_3p, "SetKeyValue" }, // pfnSetKeyValue
|
||||
{ mFALSE, 12, api_caller_void_args_i3p, "SetClientKeyValue" }, // pfnSetClientKeyValue
|
||||
{ mFALSE, 9, api_caller_int_args_p, "IsMapValid" }, // pfnIsMapValid
|
||||
{ mFALSE, 9, api_caller_void_args_p3i, "StaticDecal" }, // pfnStaticDecal
|
||||
{ mFALSE, 9, api_caller_int_args_p, "PrecacheGeneric" }, // pfnPrecacheGeneric
|
||||
{ mFALSE, 10, api_caller_int_args_p, "GetPlayerUserId" }, // pfnGetPlayerUserId
|
||||
{ mFALSE, 9, api_caller_void_args_pip2f4i2p, "BuildSoundMsg" }, // pfnBuildSoundMsg
|
||||
{ mFALSE, 9, api_caller_int_args_void, "IsDedicatedServer" }, // pfnIsDedicatedServer
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "CVarGetPointer" }, // pfnCVarGetPointer
|
||||
{ mFALSE, 9, api_caller_uint_args_p, "GetPlayerWONId" }, // pfnGetPlayerWONId
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "Info_RemoveKey" }, // pfnInfo_RemoveKey
|
||||
{ mFALSE, 15, api_caller_ptr_args_2p, "GetPhysicsKeyValue" }, // pfnGetPhysicsKeyValue
|
||||
{ mFALSE, 14, api_caller_void_args_3p, "SetPhysicsKeyValue" }, // pfnSetPhysicsKeyValue
|
||||
{ mFALSE, 15, api_caller_ptr_args_p, "GetPhysicsInfoString" }, // pfnGetPhysicsInfoString
|
||||
{ mFALSE, 13, api_caller_ushort_args_ip, "PrecacheEvent" }, // pfnPrecacheEvent
|
||||
{ mFALSE, 9, api_caller_void_args_ipusf2p2f4i,"PlaybackEvent" }, // pfnPlaybackEvent
|
||||
{ mFALSE, 31, api_caller_ptr_args_p, "SetFatPVS" }, // pfnSetFatPVS
|
||||
{ mFALSE, 31, api_caller_ptr_args_p, "SetFatPAS" }, // pfnSetFatPAS
|
||||
{ mFALSE, 50, api_caller_int_args_2p, "CheckVisibility" }, // pfnCheckVisibility
|
||||
{ mFALSE, 37, api_caller_void_args_2p, "DeltaSetField" }, // pfnDeltaSetField
|
||||
{ mFALSE, 38, api_caller_void_args_2p, "DeltaUnsetField" }, // pfnDeltaUnsetField
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "DeltaAddEncoder" }, // pfnDeltaAddEncoder
|
||||
{ mFALSE, 45, api_caller_int_args_void, "GetCurrentPlayer" }, // pfnGetCurrentPlayer
|
||||
{ mFALSE, 14, api_caller_int_args_p, "CanSkipPlayer" }, // pfnCanSkipPlayer
|
||||
{ mFALSE, 9, api_caller_int_args_2p, "DeltaFindField" }, // pfnDeltaFindField
|
||||
{ mFALSE, 37, api_caller_void_args_pi, "DeltaSetFieldByIndex" }, // pfnDeltaSetFieldByIndex
|
||||
{ mFALSE, 38, api_caller_void_args_pi, "DeltaUnsetFieldByIndex" }, // pfnDeltaUnsetFieldByIndex
|
||||
{ mFALSE, 9, api_caller_void_args_2i, "SetGroupMask" }, // pfnSetGroupMask
|
||||
{ mFALSE, 9, api_caller_int_args_ip, "engCreateInstancedBaseline" }, // pfnCreateInstancedBaseline // d'oh, CreateInstancedBaseline in dllapi too
|
||||
{ mFALSE, 9, api_caller_void_args_2p, "Cvar_DirectSet" }, // pfnCvar_DirectSet
|
||||
{ mFALSE, 9, api_caller_void_args_i3p, "ForceUnmodified" }, // pfnForceUnmodified
|
||||
{ mFALSE, 9, api_caller_void_args_3p, "GetPlayerStats" }, // pfnGetPlayerStats
|
||||
{ mFALSE, 3, api_caller_void_args_2p, "AddServerCommand" }, // pfnAddServerCommand
|
||||
// Added in SDK 2.2:
|
||||
{ mFALSE, 9, api_caller_int_args_2i, "Voice_GetClientListening" }, // Voice_GetClientListening
|
||||
{ mFALSE, 9, api_caller_int_args_3i, "Voice_SetClientListening" }, // Voice_SetClientListening
|
||||
// Added for HL 1109 (no SDK update):
|
||||
{ mFALSE, 9, api_caller_ptr_args_p, "GetPlayerAuthId" }, // pfnGetPlayerAuthId
|
||||
// Added 2003/11/10 (no SDK update):
|
||||
{ mFALSE, 30, api_caller_ptr_args_2p, "SequenceGet" }, // pfnSequenceGet
|
||||
{ mFALSE, 30, api_caller_ptr_args_pip, "SequencePickSentence" }, // pfnSequencePickSentence
|
||||
{ mFALSE, 30, api_caller_int_args_p, "GetFileSize" }, // pfnGetFileSize
|
||||
{ mFALSE, 30, api_caller_uint_args_p, "GetApproxWavePlayLen" }, // pfnGetApproxWavePlayLen
|
||||
{ mFALSE, 30, api_caller_int_args_void, "IsCareerMatch" }, // pfnIsCareerMatch
|
||||
{ mFALSE, 30, api_caller_int_args_p, "GetLocalizedStringLength" }, // pfnGetLocalizedStringLength
|
||||
{ mFALSE, 30, api_caller_void_args_i, "RegisterTutorMessageShown" }, // pfnRegisterTutorMessageShown
|
||||
{ mFALSE, 30, api_caller_int_args_i, "GetTimesTutorMessageShown" }, // pfnGetTimesTutorMessageShown
|
||||
{ mFALSE, 30, api_caller_void_args_pi, "ProcessTutorMessageDecayBuffer" }, // pfnProcessTutorMessageDecayBuffer
|
||||
{ mFALSE, 30, api_caller_void_args_pi, "ConstructTutorMessageDecayBuffer" }, // pfnConstructTutorMessageDecayBuffer
|
||||
{ mFALSE, 9, api_caller_void_args_void, "ResetTutorMessageDecayData" }, // pfnResetTutorMessageDecayData
|
||||
// Added 2005/08/11 (no SDK update):
|
||||
{ mFALSE, 3, api_caller_void_args_2p, "QueryClientCvarValue" }, // pfnQueryClientCvarValue
|
||||
// Added 2005/11/21 (no SDK update):
|
||||
{ mFALSE, 3, api_caller_void_args_2pi, "QueryClientCvarValue2" }, // pfnQueryClientCvarValue2
|
||||
// Added 2009-06-17 (no SDK update):
|
||||
{ mFALSE, 8, api_caller_int_args_2p, "EngCheckParm" }, // pfnEngCheckParm
|
||||
// end
|
||||
{ mFALSE, 0, NULL, NULL },
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
make HOST=cygwin TARGET=win32 OPT=opt
|
||||
make HOST=cygwin OPT=opt
|
||||
make HOST=cygwin TARGET=amd64 OPT=opt
|
||||
@@ -1,513 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// commands_meta.cpp - implementation of various console commands
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h> // strtol()
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "commands_meta.h" // me
|
||||
#include "metamod.h" // Plugins, etc
|
||||
#include "log_meta.h" // META_CONS, etc
|
||||
#include "info_name.h" // VNAME, etc
|
||||
#include "vdate.h" // COMPILE_TIME, COMPILE_TZONE
|
||||
|
||||
|
||||
#ifdef META_PERFMON
|
||||
|
||||
long double total_tsc=0;
|
||||
unsigned long long count_tsc=0;
|
||||
unsigned long long active_tsc=0;
|
||||
unsigned long long min_tsc=0;
|
||||
|
||||
void DLLINTERNAL cmd_meta_tsc(void) {
|
||||
if(!count_tsc)
|
||||
return;
|
||||
|
||||
META_CONS(" ");
|
||||
META_CONS(" count_tsc: %.0f", (double)count_tsc);
|
||||
META_CONS(" mean_tsc: %.1f", (double)(total_tsc / count_tsc));
|
||||
META_CONS(" min_tsc: %.0f", (double)min_tsc);
|
||||
}
|
||||
|
||||
void DLLINTERNAL cmd_meta_reset_tsc(void) {
|
||||
total_tsc=0;
|
||||
count_tsc=0;
|
||||
min_tsc=0;
|
||||
}
|
||||
#endif /*META_PERFMON*/
|
||||
|
||||
// Register commands and cvars.
|
||||
void DLLINTERNAL meta_register_cmdcvar() {
|
||||
CVAR_REGISTER(&meta_debug);
|
||||
CVAR_REGISTER(&meta_version);
|
||||
|
||||
meta_debug_value = (int)meta_debug.value;
|
||||
|
||||
REG_SVR_COMMAND("meta", svr_meta);
|
||||
}
|
||||
|
||||
// Parse "meta" console command.
|
||||
void DLLHIDDEN svr_meta(void) {
|
||||
const char *cmd;
|
||||
cmd=CMD_ARGV(1);
|
||||
// arguments: none
|
||||
if(!strcasecmp(cmd, "version"))
|
||||
cmd_meta_version();
|
||||
else if(!strcasecmp(cmd, "gpl"))
|
||||
cmd_meta_gpl();
|
||||
else if(!strcasecmp(cmd, "refresh"))
|
||||
cmd_meta_refresh();
|
||||
else if(!strcasecmp(cmd, "list"))
|
||||
cmd_meta_pluginlist();
|
||||
else if(!strcasecmp(cmd, "cmds"))
|
||||
cmd_meta_cmdlist();
|
||||
else if(!strcasecmp(cmd, "cvars"))
|
||||
cmd_meta_cvarlist();
|
||||
else if(!strcasecmp(cmd, "game"))
|
||||
cmd_meta_game();
|
||||
else if(!strcasecmp(cmd, "config"))
|
||||
cmd_meta_config();
|
||||
// arguments: existing plugin(s)
|
||||
else if(!strcasecmp(cmd, "pause"))
|
||||
cmd_doplug(PC_PAUSE);
|
||||
else if(!strcasecmp(cmd, "unpause"))
|
||||
cmd_doplug(PC_UNPAUSE);
|
||||
else if(!strcasecmp(cmd, "unload"))
|
||||
cmd_doplug(PC_UNLOAD);
|
||||
else if(!strcasecmp(cmd, "force_unload"))
|
||||
cmd_doplug(PC_FORCE_UNLOAD);
|
||||
else if(!strcasecmp(cmd, "reload"))
|
||||
cmd_doplug(PC_RELOAD);
|
||||
else if(!strcasecmp(cmd, "retry"))
|
||||
cmd_doplug(PC_RETRY);
|
||||
else if(!strcasecmp(cmd, "clear"))
|
||||
cmd_doplug(PC_CLEAR);
|
||||
else if(!strcasecmp(cmd, "info"))
|
||||
cmd_doplug(PC_INFO);
|
||||
else if(!strcasecmp(cmd, "require"))
|
||||
cmd_doplug(PC_REQUIRE);
|
||||
// arguments: filename, description
|
||||
else if(!strcasecmp(cmd, "load"))
|
||||
cmd_meta_load();
|
||||
#ifdef META_PERFMON
|
||||
else if(!strcasecmp(cmd, "tsc"))
|
||||
cmd_meta_tsc();
|
||||
else if(!strcasecmp(cmd, "reset_tsc"))
|
||||
cmd_meta_reset_tsc();
|
||||
#endif /*META_PERFMON*/
|
||||
// unrecognized
|
||||
else {
|
||||
META_CONS("Unrecognized meta command: %s", cmd);
|
||||
cmd_meta_usage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse "meta" client command.
|
||||
void DLLINTERNAL client_meta(edict_t *pEntity) {
|
||||
const char *cmd;
|
||||
cmd=CMD_ARGV(1);
|
||||
META_LOG("ClientCommand 'meta %s' from player '%s'",
|
||||
CMD_ARGS(), STRING(pEntity->v.netname));
|
||||
// arguments: none
|
||||
if(strmatch(cmd, "version"))
|
||||
client_meta_version(pEntity);
|
||||
else if(strmatch(cmd, "list"))
|
||||
client_meta_pluginlist(pEntity);
|
||||
else if(strmatch(cmd, "aybabtu"))
|
||||
client_meta_aybabtu(pEntity);
|
||||
// unrecognized
|
||||
else {
|
||||
META_CLIENT(pEntity, "Unrecognized meta command: %s", cmd);
|
||||
client_meta_usage(pEntity);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Print usage for "meta" console command.
|
||||
void DLLINTERNAL cmd_meta_usage(void) {
|
||||
META_CONS("usage: meta <command> [<arguments>]");
|
||||
META_CONS("valid commands are:");
|
||||
META_CONS(" version - display metamod version info");
|
||||
META_CONS(" game - display gamedll info");
|
||||
META_CONS(" list - list plugins currently loaded");
|
||||
META_CONS(" cmds - list console cmds registered by plugins");
|
||||
META_CONS(" cvars - list cvars registered by plugins");
|
||||
META_CONS(" refresh - load/unload any new/deleted/updated plugins");
|
||||
META_CONS(" config - show config info loaded from config.ini");
|
||||
META_CONS(" load <name> - find and load a plugin with the given name");
|
||||
META_CONS(" unload <plugin> - unload a loaded plugin");
|
||||
META_CONS(" reload <plugin> - unload a plugin and load it again");
|
||||
META_CONS(" info <plugin> - show all information about a plugin");
|
||||
META_CONS(" pause <plugin> - pause a loaded, running plugin");
|
||||
META_CONS(" unpause <plugin> - unpause a previously paused plugin");
|
||||
META_CONS(" retry <plugin> - retry a plugin that previously failed its action");
|
||||
META_CONS(" clear <plugin> - clear a failed plugin from the list");
|
||||
META_CONS(" force_unload <plugin> - forcibly unload a loaded plugin");
|
||||
META_CONS(" require <plugin> - exit server if plugin not loaded/running");
|
||||
}
|
||||
|
||||
// Print usage for "meta" client command.
|
||||
void DLLINTERNAL client_meta_usage(edict_t *pEntity) {
|
||||
META_CLIENT(pEntity, "usage: meta <command> [<arguments>]");
|
||||
META_CLIENT(pEntity, "valid commands are:");
|
||||
META_CLIENT(pEntity, " version - display metamod version info");
|
||||
META_CLIENT(pEntity, " list - list plugins currently loaded");
|
||||
}
|
||||
|
||||
// "meta aybabtu" client command.
|
||||
void DLLINTERNAL client_meta_aybabtu(edict_t *pEntity) {
|
||||
META_CLIENT(pEntity, "%s", "All Your Base Are Belong To Us");
|
||||
}
|
||||
|
||||
// "meta version" console command.
|
||||
void DLLINTERNAL cmd_meta_version(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta version");
|
||||
return;
|
||||
}
|
||||
META_CONS("%s v%s %s (%s)", VNAME, VVERSION, VDATE, META_INTERFACE_VERSION);
|
||||
META_CONS("by %s", VAUTHOR);
|
||||
META_CONS(" %s", VURL);
|
||||
META_CONS(" Patch: %s v%d", VPATCH_NAME, VPATCH_IVERSION);
|
||||
META_CONS(" by %s", VPATCH_AUTHOR);
|
||||
META_CONS(" %s", VPATCH_WEBSITE);
|
||||
META_CONS("compiled: %s %s (%s)", COMPILE_TIME, COMPILE_TZONE, OPT_TYPE);
|
||||
}
|
||||
|
||||
// "meta version" client command.
|
||||
void DLLINTERNAL client_meta_version(edict_t *pEntity) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CLIENT(pEntity, "usage: meta version");
|
||||
return;
|
||||
}
|
||||
META_CLIENT(pEntity, "%s v%s %s (%s)", VNAME, VVERSION, VDATE, META_INTERFACE_VERSION);
|
||||
META_CLIENT(pEntity, "by %s", VAUTHOR);
|
||||
META_CLIENT(pEntity, " %s", VURL);
|
||||
META_CLIENT(pEntity, " Patch: %s v%d", VPATCH_NAME, VPATCH_IVERSION);
|
||||
META_CLIENT(pEntity, " by %s", VPATCH_AUTHOR);
|
||||
META_CLIENT(pEntity, " %s", VPATCH_WEBSITE);
|
||||
META_CLIENT(pEntity, "compiled: %s %s (%s)", COMPILE_TIME, COMPILE_TZONE, OPT_TYPE);
|
||||
META_CLIENT(pEntity, "ifvers: %s", META_INTERFACE_VERSION);
|
||||
}
|
||||
|
||||
// "meta gpl" console command.
|
||||
void DLLINTERNAL cmd_meta_gpl(void) {
|
||||
META_CONS("%s version %s %s", VNAME, VVERSION, VDATE);
|
||||
META_CONS("Copyright (c) 2001-%s %s", COPYRIGHT_YEAR, VAUTHOR);
|
||||
META_CONS("");
|
||||
META_CONS(" %s is free software; you can redistribute it and/or", VNAME);
|
||||
META_CONS(" modify it under the terms of the GNU General Public License");
|
||||
META_CONS(" as published by the Free Software Foundation; either");
|
||||
META_CONS(" version 2 of the License, or (at your option) any later");
|
||||
META_CONS(" version.");
|
||||
META_CONS(" ");
|
||||
META_CONS(" %s is distributed in the hope that it will be useful,", VNAME);
|
||||
META_CONS(" but WITHOUT ANY WARRANTY; without even the implied warranty");
|
||||
META_CONS(" of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.");
|
||||
META_CONS(" See the GNU General Public License for more details.");
|
||||
META_CONS(" ");
|
||||
META_CONS(" You should have received a copy of the GNU General Public");
|
||||
META_CONS(" License along with Metamod; if not, write to the Free");
|
||||
META_CONS(" Software Foundation, Inc., 59 Temple Place, Suite 330,");
|
||||
META_CONS(" Boston, MA 02111-1307 USA");
|
||||
META_CONS(" ");
|
||||
META_CONS(" In addition, as a special exception, the author gives");
|
||||
META_CONS(" permission to link the code of this program with the");
|
||||
META_CONS(" Half-Life Game Engine (\"HL Engine\") and Modified Game");
|
||||
META_CONS(" Libraries (\"MODs\") developed by Valve, L.L.C (\"Valve\").");
|
||||
META_CONS(" You must obey the GNU General Public License in all");
|
||||
META_CONS(" respects for all of the code used other than the HL Engine");
|
||||
META_CONS(" and MODs from Valve. If you modify this file, you may");
|
||||
META_CONS(" extend this exception to your version of the file, but you");
|
||||
META_CONS(" are not obligated to do so. If you do not wish to do so,");
|
||||
META_CONS(" delete this exception statement from your version.");
|
||||
}
|
||||
|
||||
// "meta game" console command.
|
||||
void DLLINTERNAL cmd_meta_game(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta game");
|
||||
return;
|
||||
}
|
||||
META_CONS("GameDLL info:");
|
||||
META_CONS(" name: %s", GameDLL.name);
|
||||
META_CONS(" desc: %s", GameDLL.desc);
|
||||
META_CONS(" gamedir: %s", GameDLL.gamedir);
|
||||
META_CONS(" dll file: %s", GameDLL.file);
|
||||
META_CONS("dll pathname: %s", GameDLL.pathname);
|
||||
RegMsgs->show();
|
||||
}
|
||||
|
||||
// "meta refresh" console command.
|
||||
void DLLINTERNAL cmd_meta_refresh(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta refresh");
|
||||
return;
|
||||
}
|
||||
META_LOG("Refreshing the plugins on demand...");
|
||||
if(Plugins->refresh(PT_ANYTIME) != mTRUE) {
|
||||
META_LOG("Refresh failed.");
|
||||
}
|
||||
}
|
||||
|
||||
// "meta list" console command.
|
||||
void DLLINTERNAL cmd_meta_pluginlist(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta list");
|
||||
return;
|
||||
}
|
||||
Plugins->show();
|
||||
}
|
||||
|
||||
// "meta list" client command.
|
||||
void DLLINTERNAL client_meta_pluginlist(edict_t *pEntity) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CLIENT(pEntity, "usage: meta list");
|
||||
return;
|
||||
}
|
||||
Plugins->show_client(pEntity);
|
||||
}
|
||||
|
||||
// "meta cmds" console command.
|
||||
void DLLINTERNAL cmd_meta_cmdlist(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta cmds");
|
||||
return;
|
||||
}
|
||||
RegCmds->show();
|
||||
}
|
||||
|
||||
// "meta cvars" console command.
|
||||
void DLLINTERNAL cmd_meta_cvarlist(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta cvars");
|
||||
return;
|
||||
}
|
||||
RegCvars->show();
|
||||
}
|
||||
|
||||
// "meta config" console command.
|
||||
void DLLINTERNAL cmd_meta_config(void) {
|
||||
if(CMD_ARGC() != 2) {
|
||||
META_CONS("usage: meta cvars");
|
||||
return;
|
||||
}
|
||||
Config->show();
|
||||
}
|
||||
|
||||
// gamedir/filename
|
||||
// gamedir/dlls/filename
|
||||
//
|
||||
// dir/mm_file
|
||||
// dir/file
|
||||
//
|
||||
// path
|
||||
// path_mm
|
||||
// path_MM
|
||||
// path.so, path.dll
|
||||
// path_i386.so, path_i486.so, etc
|
||||
|
||||
// "meta load" console command.
|
||||
void DLLINTERNAL cmd_meta_load(void) {
|
||||
int argc;
|
||||
const char *args;
|
||||
argc=CMD_ARGC();
|
||||
if(argc < 3) {
|
||||
META_CONS("usage: meta load <name> [<description>]");
|
||||
META_CONS(" where <name> is an identifier used to locate the plugin file.");
|
||||
META_CONS(" The system will look for a number of files based on this name, including:");
|
||||
META_CONS(" name");
|
||||
#ifdef linux
|
||||
META_CONS(" name.so");
|
||||
META_CONS(" name_mm.so");
|
||||
META_CONS(" name_MM.so");
|
||||
META_CONS(" mm_name.so");
|
||||
#ifdef __x86_64__
|
||||
META_CONS(" name_amd64.so");
|
||||
META_CONS(" name_x86_64.so");
|
||||
#else
|
||||
META_CONS(" name_i386.so");
|
||||
META_CONS(" name_i686.so");
|
||||
#endif
|
||||
#elif defined(_WIN32)
|
||||
META_CONS(" name.dll");
|
||||
META_CONS(" name_mm.dll");
|
||||
META_CONS(" mm_name.dll");
|
||||
#endif /* linux */
|
||||
META_CONS(" in a number of directories, including:");
|
||||
META_CONS(" <gamedir>");
|
||||
META_CONS(" <gamedir>/dlls");
|
||||
META_CONS(" <given path, if absolute>");
|
||||
return;
|
||||
}
|
||||
args=CMD_ARGS();
|
||||
// cmd_addload() handles all the feedback to the console..
|
||||
Plugins->cmd_addload(args);
|
||||
}
|
||||
|
||||
// Handle various console commands that refer to a known/loaded plugin.
|
||||
void DLLINTERNAL cmd_doplug(PLUG_CMD pcmd) {
|
||||
int i=0, argc;
|
||||
const char *cmd, *arg;
|
||||
MPlugin *findp;
|
||||
|
||||
argc=CMD_ARGC();
|
||||
cmd=CMD_ARGV(1);
|
||||
if(argc < 3) {
|
||||
META_CONS("usage: meta %s <plugin> [<plugin> ...]", cmd);
|
||||
META_CONS(" where <plugin> can be either the plugin index #");
|
||||
META_CONS(" or a non-ambiguous prefix string matching name, desc, file, or logtag");
|
||||
return;
|
||||
}
|
||||
// i=2 to skip first arg, as that's the "cmd"
|
||||
for(i=2; i < argc; i++) {
|
||||
int pindex;
|
||||
char *endptr;
|
||||
|
||||
arg=CMD_ARGV(i);
|
||||
|
||||
// try to match plugin id first
|
||||
pindex = strtol(arg, &endptr, 10);
|
||||
if(*arg && !*endptr)
|
||||
findp=Plugins->find(pindex);
|
||||
// else try to match some string (prefix)
|
||||
else
|
||||
findp=Plugins->find_match(arg);
|
||||
|
||||
// Require that:
|
||||
// - specified plugin was found in the list of current plugins
|
||||
// - plugin successfully loaded and began running
|
||||
// Otherwise, print error and exit.
|
||||
if(pcmd==PC_REQUIRE) {
|
||||
if(findp && findp->status >= PL_RUNNING) {
|
||||
META_DEBUG(3, ("Required plugin '%s' found loaded and running.",
|
||||
arg));
|
||||
return;
|
||||
}
|
||||
// Output to both places, because we don't want the admin
|
||||
// to miss this..
|
||||
if(!findp && meta_errno == ME_NOTUNIQ) {
|
||||
META_ERROR("Unique match for required plugin '%s' was not found! Exiting.", arg);
|
||||
META_CONS("\nERROR: Unique match for required plugin '%s' was not found! Exiting.\n", arg);
|
||||
}
|
||||
else if(!findp) {
|
||||
META_ERROR("Required plugin '%s' was not found! Exiting.",
|
||||
arg);
|
||||
META_CONS("\nERROR: Required plugin '%s' was not found! Exiting.\n",
|
||||
arg);
|
||||
}
|
||||
else {
|
||||
META_ERROR("Required plugin '%s' did not load successfully! (status=%s) Exiting.", arg, findp->str_status(ST_SIMPLE));
|
||||
META_CONS("\nERROR: Required plugin '%s' did not load successfully! (status=%s) Exiting.\n", arg, findp->str_status(ST_SIMPLE));
|
||||
}
|
||||
// Allow chance to read the message, before any window closes.
|
||||
do_exit(1);
|
||||
}
|
||||
|
||||
if(!findp) {
|
||||
if(meta_errno == ME_NOTUNIQ)
|
||||
META_CONS("Couldn't find unique plugin matching '%s'", arg);
|
||||
else
|
||||
META_CONS("Couldn't find plugin matching '%s'", arg);
|
||||
return;
|
||||
}
|
||||
|
||||
if(pcmd==PC_PAUSE) {
|
||||
if(findp->pause())
|
||||
META_CONS("Paused plugin '%s'", findp->desc);
|
||||
else
|
||||
META_CONS("Pause failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_UNPAUSE) {
|
||||
if(findp->unpause())
|
||||
META_CONS("Unpaused plugin '%s'", findp->desc);
|
||||
else
|
||||
META_CONS("Unpause failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_UNLOAD) {
|
||||
findp->action=PA_UNLOAD;
|
||||
if(findp->unload(PT_ANYTIME, PNL_COMMAND, PNL_COMMAND)) {
|
||||
META_CONS("Unloaded plugin '%s'", findp->desc);
|
||||
Plugins->show();
|
||||
}
|
||||
else if(meta_errno == ME_DELAYED)
|
||||
META_CONS("Unload delayed for plugin '%s'", findp->desc);
|
||||
else
|
||||
META_CONS("Unload failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_FORCE_UNLOAD) {
|
||||
findp->action=PA_UNLOAD;
|
||||
if(findp->unload(PT_ANYTIME, PNL_CMD_FORCED, PNL_CMD_FORCED)) {
|
||||
META_CONS("Forced unload plugin '%s'", findp->desc);
|
||||
Plugins->show();
|
||||
}
|
||||
else
|
||||
META_CONS("Forced unload failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_RELOAD) {
|
||||
findp->action=PA_RELOAD;
|
||||
if(findp->reload(PT_ANYTIME, PNL_COMMAND))
|
||||
META_CONS("Reloaded plugin '%s'", findp->desc);
|
||||
else if(meta_errno == ME_DELAYED)
|
||||
META_CONS("Reload delayed for plugin '%s'", findp->desc);
|
||||
else if(meta_errno == ME_NOTALLOWED)
|
||||
META_CONS("Reload not allowed for plugin '%s' now, only allowed %s", findp->desc, findp->str_loadable(SL_ALLOWED));
|
||||
else
|
||||
META_CONS("Reload failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_RETRY) {
|
||||
if(findp->retry(PT_ANYTIME, PNL_COMMAND))
|
||||
META_CONS("Retry succeeded for plugin '%s'", findp->desc);
|
||||
else
|
||||
META_CONS("Retry failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_CLEAR) {
|
||||
if(findp->clear()) {
|
||||
META_CONS("Cleared failed plugin '%s' from list", findp->desc);
|
||||
Plugins->show();
|
||||
}
|
||||
else
|
||||
META_CONS("Clear failed for plugin '%s'", findp->desc);
|
||||
}
|
||||
else if(pcmd==PC_INFO)
|
||||
findp->show();
|
||||
else {
|
||||
META_WARNING("Unexpected plug_cmd: %d", pcmd);
|
||||
META_CONS("Command failed; see log");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// conf_meta.cpp - configfile reading routines
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h> // FILE,
|
||||
#include <stdlib.h> // atoi
|
||||
#include <ctype.h> // isdigit
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "conf_meta.h" // me
|
||||
#include "support_meta.h" // strmatch
|
||||
#include "osdep.h" // strtok,
|
||||
|
||||
MConfig::MConfig(void)
|
||||
: list(NULL), filename(NULL), debuglevel(0), gamedll(NULL),
|
||||
plugins_file(NULL), exec_cfg(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// Initialize default values from the stored options struct. Has to happen
|
||||
// _after_ constructor, so that all the fields are allocated (d'oh).
|
||||
void DLLINTERNAL MConfig::init(option_t *global_options) {
|
||||
option_t *optp;
|
||||
list=global_options;
|
||||
for(optp=list; optp->name; optp++)
|
||||
set(optp, optp->init);
|
||||
}
|
||||
|
||||
option_t * DLLINTERNAL MConfig::find(const char *lookup) {
|
||||
option_t *optp;
|
||||
|
||||
for(optp=list; optp->name && !strmatch(optp->name, lookup); optp++);
|
||||
if(optp->name)
|
||||
return(optp);
|
||||
else
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
mBOOL DLLINTERNAL MConfig::set(const char *key, const char *value) {
|
||||
option_t *optp;
|
||||
optp=find(key);
|
||||
if(optp)
|
||||
return(set(optp, value));
|
||||
else
|
||||
RETURN_ERRNO(mFALSE, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
mBOOL DLLINTERNAL MConfig::set(option_t *setp, const char *setstr) {
|
||||
char pathbuf[PATH_MAX];
|
||||
int *optval = (int *) setp->dest;
|
||||
char **optstr = (char **) setp->dest;
|
||||
// cvar_t *optcvar = (cvar_t *) setp->dest;
|
||||
// SETOPT_FN optcmd = (SETOPT_FN) setp->dest;
|
||||
|
||||
if(!setstr)
|
||||
return(mTRUE);
|
||||
|
||||
switch(setp->type) {
|
||||
case CF_INT:
|
||||
if(!isdigit(setstr[0])) {
|
||||
META_WARNING("option '%s' invalid format '%s'", setp->name, setstr);
|
||||
RETURN_ERRNO(mFALSE, ME_FORMAT);
|
||||
}
|
||||
*optval=atoi(setstr);
|
||||
META_DEBUG(3, ("set config int: %s = %d", setp->name, *optval));
|
||||
break;
|
||||
case CF_BOOL:
|
||||
if(strcasematch(setstr, "true")
|
||||
|| strcasematch(setstr, "yes")
|
||||
|| strmatch(setstr, "1"))
|
||||
{
|
||||
*optval=1;
|
||||
}
|
||||
else if(strcasematch(setstr, "false")
|
||||
|| strcasematch(setstr, "no")
|
||||
|| strmatch(setstr, "0"))
|
||||
{
|
||||
*optval=0;
|
||||
}
|
||||
else {
|
||||
META_WARNING("option '%s' invalid format '%s'", setp->name, setstr);
|
||||
RETURN_ERRNO(mFALSE, ME_FORMAT);
|
||||
}
|
||||
META_DEBUG(3, ("set config bool: %s = %s", setp->name, *optval ? "true" : "false"));
|
||||
break;
|
||||
case CF_STR:
|
||||
if(*optstr)
|
||||
free(*optstr);
|
||||
*optstr=strdup(setstr);
|
||||
META_DEBUG(3, ("set config string: %s = %s", setp->name, *optstr));
|
||||
break;
|
||||
case CF_PATH:
|
||||
if(*optstr)
|
||||
free(*optstr);
|
||||
full_gamedir_path(setstr, pathbuf);
|
||||
*optstr=strdup(pathbuf);
|
||||
META_DEBUG(3, ("set config path: %s = %s", setp->name, *optstr));
|
||||
break;
|
||||
#if 0
|
||||
case CF_CVAR:
|
||||
CVAR_SET_STRING(optcvar->name, setstr);
|
||||
META_DEBUG(3, ("set config cvar: %s = %s", optcvar->name, setstr));
|
||||
break;
|
||||
case CF_CMD:
|
||||
optcmd(setp->name, setstr);
|
||||
META_DEBUG(3, ("set config command: %s, %s", optcvar->name, setstr));
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
META_WARNING("unrecognized config type '%d'", setp->type);
|
||||
RETURN_ERRNO(mFALSE, ME_ARGUMENT);
|
||||
}
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
mBOOL DLLINTERNAL MConfig::load(const char *fn) {
|
||||
FILE *fp;
|
||||
char loadfile[PATH_MAX];
|
||||
char line[MAX_CONF_LEN];
|
||||
char *optname, *optval;
|
||||
option_t *optp;
|
||||
int ln;
|
||||
|
||||
// Make full pathname (from gamedir if relative, collapse "..",
|
||||
// backslashes, etc).
|
||||
full_gamedir_path(fn, loadfile);
|
||||
|
||||
fp=fopen(loadfile, "r");
|
||||
if(!fp) {
|
||||
META_WARNING("unable to open config file '%s': %s", loadfile,
|
||||
strerror(errno));
|
||||
RETURN_ERRNO(mFALSE, ME_NOFILE);
|
||||
}
|
||||
|
||||
META_DEBUG(2, ("Loading from config file: %s", loadfile));
|
||||
for(ln=1; !feof(fp) && fgets(line, sizeof(line), fp); ln++) {
|
||||
if(line[0]=='#')
|
||||
continue;
|
||||
if(line[0]==';')
|
||||
continue;
|
||||
if(strnmatch(line, "//", 2))
|
||||
continue;
|
||||
if(!(optname=strtok(line, " \t\r\n"))) {
|
||||
META_WARNING("'%s' line %d: bad config format: missing option",
|
||||
loadfile, ln);
|
||||
continue;
|
||||
}
|
||||
if(!(optval=strtok(NULL, "\r\n"))) {
|
||||
META_WARNING("'%s' line %d: bad config format: missing value",
|
||||
loadfile, ln);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!(optp=find(optname))) {
|
||||
META_WARNING("'%s' line %d: unknown option name '%s'",
|
||||
loadfile, ln, optname);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!set(optp, optval)) {
|
||||
META_WARNING("'%s' line %d: unable to set option '%s' value '%s'",
|
||||
loadfile, ln, optname, optval);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
filename=strdup(loadfile);
|
||||
fclose(fp);
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
void DLLINTERNAL MConfig::show(void) {
|
||||
option_t *optp;
|
||||
if(filename)
|
||||
META_CONS("%s and %s:", "Config options from localinfo", filename);
|
||||
else
|
||||
META_CONS("%s:", "Config options from localinfo");
|
||||
for(optp=list; optp->name; optp++) {
|
||||
int *optval = (int *) optp->dest;
|
||||
char **optstr = (char **) optp->dest;
|
||||
// cvar_t *optcvar = (cvar_t *) optp->dest;
|
||||
// SETOPT_FN optcmd = (SETOPT_FN) optp->dest;
|
||||
switch(optp->type) {
|
||||
case CF_INT:
|
||||
META_CONS(" %-20s\t%d\n", optp->name, *optval);
|
||||
break;
|
||||
case CF_BOOL:
|
||||
META_CONS(" %-20s\t%s\n", optp->name,
|
||||
*optval ? "true" : "false");
|
||||
break;
|
||||
case CF_STR:
|
||||
case CF_PATH:
|
||||
META_CONS(" %-20s\t%s\n", optp->name,
|
||||
*optstr ? *optstr : "");
|
||||
break;
|
||||
#if 0
|
||||
case CF_CVAR:
|
||||
META_CONS(" %-20s\tstores in: %s\n", optp->name, optcvar->name);
|
||||
break;
|
||||
case CF_CMD:
|
||||
META_CONS(" %-20s\tparsed by: %d\n", optp->name, (int) optcmd);
|
||||
break;
|
||||
#endif
|
||||
case CF_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,513 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// dllapi.cpp - implementation of Half-Life DLL routines
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stddef.h> // offsetof
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "dllapi.h" // me
|
||||
#include "metamod.h" // SETUP_API_CALLS, etc
|
||||
#include "api_info.h" // dllapi_info, etc
|
||||
#include "commands_meta.h" // client_meta, etc
|
||||
#include "log_meta.h" // META_ERROR, etc
|
||||
#include "api_hook.h"
|
||||
|
||||
|
||||
// Original DLL routines, functions returning "void".
|
||||
#define META_DLLAPI_HANDLE_void(FN_TYPE, pfnName, pack_args_type, pfn_args) \
|
||||
API_START_TSC_TRACKING(); \
|
||||
API_PACK_ARGS(pack_args_type, pfn_args); \
|
||||
main_hook_function_void(offsetof(dllapi_info_t, pfnName), e_api_dllapi, offsetof(DLL_FUNCTIONS, pfnName), &packed_args); \
|
||||
API_END_TSC_TRACKING()
|
||||
|
||||
// Original DLL routines, functions returning an actual value.
|
||||
#define META_DLLAPI_HANDLE(ret_t, ret_init, FN_TYPE, pfnName, pack_args_type, pfn_args) \
|
||||
API_START_TSC_TRACKING(); \
|
||||
API_PACK_ARGS(pack_args_type, pfn_args); \
|
||||
class_ret_t ret_val(main_hook_function(class_ret_t((ret_t)ret_init), offsetof(dllapi_info_t, pfnName), e_api_dllapi, offsetof(DLL_FUNCTIONS, pfnName), &packed_args)); \
|
||||
API_END_TSC_TRACKING()
|
||||
|
||||
// The "new" api routines (just 3 right now), functions returning "void".
|
||||
#define META_NEWAPI_HANDLE_void(FN_TYPE, pfnName, pack_args_type, pfn_args) \
|
||||
API_START_TSC_TRACKING(); \
|
||||
API_PACK_ARGS(pack_args_type, pfn_args); \
|
||||
main_hook_function_void(offsetof(newapi_info_t, pfnName), e_api_newapi, offsetof(NEW_DLL_FUNCTIONS, pfnName), &packed_args); \
|
||||
API_END_TSC_TRACKING()
|
||||
|
||||
// The "new" api routines (just 3 right now), functions returning an actual value.
|
||||
#define META_NEWAPI_HANDLE(ret_t, ret_init, FN_TYPE, pfnName, pack_args_type, pfn_args) \
|
||||
API_START_TSC_TRACKING(); \
|
||||
API_PACK_ARGS(pack_args_type, pfn_args); \
|
||||
class_ret_t ret_val(main_hook_function(class_ret_t((ret_t)ret_init), offsetof(newapi_info_t, pfnName), e_api_newapi, offsetof(NEW_DLL_FUNCTIONS, pfnName), &packed_args)); \
|
||||
API_END_TSC_TRACKING()
|
||||
|
||||
|
||||
// From SDK dlls/game.cpp:
|
||||
static void mm_GameDLLInit(void) {
|
||||
META_DLLAPI_HANDLE_void(FN_GAMEINIT, pfnGameInit, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
|
||||
// From SDK dlls/cbase.cpp:
|
||||
static int mm_DispatchSpawn(edict_t *pent) {
|
||||
// 0==Success, -1==Failure ?
|
||||
META_DLLAPI_HANDLE(int, 0, FN_DISPATCHSPAWN, pfnSpawn, p, (pent));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static void mm_DispatchThink(edict_t *pent) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHTHINK, pfnThink, p, (pent));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_DispatchUse(edict_t *pentUsed, edict_t *pentOther) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHUSE, pfnUse, 2p, (pentUsed, pentOther));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_DispatchTouch(edict_t *pentTouched, edict_t *pentOther) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHTOUCH, pfnTouch, 2p, (pentTouched, pentOther));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_DispatchBlocked(edict_t *pentBlocked, edict_t *pentOther) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHBLOCKED, pfnBlocked, 2p, (pentBlocked, pentOther));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_DispatchKeyValue(edict_t *pentKeyvalue, KeyValueData *pkvd) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHKEYVALUE, pfnKeyValue, 2p, (pentKeyvalue, pkvd));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_DispatchSave(edict_t *pent, SAVERESTOREDATA *pSaveData) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHSAVE, pfnSave, 2p, (pent, pSaveData));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static int mm_DispatchRestore(edict_t *pent, SAVERESTOREDATA *pSaveData, int globalEntity) {
|
||||
// 0==Success, -1==Failure ?
|
||||
META_DLLAPI_HANDLE(int, 0, FN_DISPATCHRESTORE, pfnRestore, 2pi, (pent, pSaveData, globalEntity));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static void mm_DispatchObjectCollsionBox(edict_t *pent) {
|
||||
META_DLLAPI_HANDLE_void(FN_DISPATCHOBJECTCOLLISIONBOX, pfnSetAbsBox, p, (pent));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_SaveWriteFields(SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount) {
|
||||
META_DLLAPI_HANDLE_void(FN_SAVEWRITEFIELDS, pfnSaveWriteFields, 4pi, (pSaveData, pname, pBaseData, pFields, fieldCount));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_SaveReadFields(SAVERESTOREDATA *pSaveData, const char *pname, void *pBaseData, TYPEDESCRIPTION *pFields, int fieldCount) {
|
||||
META_DLLAPI_HANDLE_void(FN_SAVEREADFIELDS, pfnSaveReadFields, 4pi, (pSaveData, pname, pBaseData, pFields, fieldCount));
|
||||
RETURN_API_void();
|
||||
}
|
||||
|
||||
// From SDK dlls/world.cpp:
|
||||
static void mm_SaveGlobalState(SAVERESTOREDATA *pSaveData) {
|
||||
META_DLLAPI_HANDLE_void(FN_SAVEGLOBALSTATE, pfnSaveGlobalState, p, (pSaveData));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_RestoreGlobalState(SAVERESTOREDATA *pSaveData) {
|
||||
META_DLLAPI_HANDLE_void(FN_RESTOREGLOBALSTATE, pfnRestoreGlobalState, p, (pSaveData));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ResetGlobalState(void) {
|
||||
META_DLLAPI_HANDLE_void(FN_RESETGLOBALSTATE, pfnResetGlobalState, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
|
||||
// From SDK dlls/client.cpp:
|
||||
static qboolean mm_ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]) {
|
||||
g_Players.clear_player_cvar_query(pEntity);
|
||||
META_DLLAPI_HANDLE(qboolean, TRUE, FN_CLIENTCONNECT, pfnClientConnect, 4p, (pEntity, pszName, pszAddress, szRejectReason));
|
||||
RETURN_API(qboolean);
|
||||
}
|
||||
static void mm_ClientDisconnect(edict_t *pEntity) {
|
||||
g_Players.clear_player_cvar_query(pEntity);
|
||||
META_DLLAPI_HANDLE_void(FN_CLIENTDISCONNECT, pfnClientDisconnect, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ClientKill(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_CLIENTKILL, pfnClientKill, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ClientPutInServer(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_CLIENTPUTINSERVER, pfnClientPutInServer, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ClientCommand(edict_t *pEntity) {
|
||||
if(Config->clientmeta && strmatch(CMD_ARGV(0), "meta")) {
|
||||
client_meta(pEntity);
|
||||
}
|
||||
META_DLLAPI_HANDLE_void(FN_CLIENTCOMMAND, pfnClientCommand, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ClientUserInfoChanged(edict_t *pEntity, char *infobuffer) {
|
||||
META_DLLAPI_HANDLE_void(FN_CLIENTUSERINFOCHANGED, pfnClientUserInfoChanged, 2p, (pEntity, infobuffer));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) {
|
||||
META_DLLAPI_HANDLE_void(FN_SERVERACTIVATE, pfnServerActivate, p2i, (pEdictList, edictCount, clientMax));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ServerDeactivate(void) {
|
||||
META_DLLAPI_HANDLE_void(FN_SERVERDEACTIVATE, pfnServerDeactivate, void, (VOID_ARG));
|
||||
// Update loaded plugins. Look for new plugins in inifile, as well as
|
||||
// any plugins waiting for a changelevel to load.
|
||||
//
|
||||
// This is done in ServerDeactivate rather than Activate, as the latter
|
||||
// isn't actually the first routine to be called on a new map. In
|
||||
// particular DispatchKeyValue and DispatchSpawn are called before
|
||||
// Activate, and we want any newly loaded plugins to be able to catch
|
||||
// these.
|
||||
//
|
||||
// So, we do this from Deactivate, which is the _last_ routine called
|
||||
// from the previous map. It's also called right before shutdown,
|
||||
// which means whenever hlds quits, it'll reload the plugins just
|
||||
// before it exits, which is rather silly, but oh well.
|
||||
Plugins->refresh(PT_CHANGELEVEL);
|
||||
Plugins->unpause_all();
|
||||
// Plugins->retry_all(PT_CHANGELEVEL);
|
||||
g_Players.clear_all_cvar_queries();
|
||||
requestid_counter = 0;
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_PlayerPreThink(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_PLAYERPRETHINK, pfnPlayerPreThink, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_PlayerPostThink(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_PLAYERPOSTTHINK, pfnPlayerPostThink, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_StartFrame(void) {
|
||||
meta_debug_value = (int)meta_debug.value;
|
||||
|
||||
META_DLLAPI_HANDLE_void(FN_STARTFRAME, pfnStartFrame, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ParmsNewLevel(void) {
|
||||
META_DLLAPI_HANDLE_void(FN_PARMSNEWLEVEL, pfnParmsNewLevel, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_ParmsChangeLevel(void) {
|
||||
META_DLLAPI_HANDLE_void(FN_PARMSCHANGELEVEL, pfnParmsChangeLevel, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static const char *mm_GetGameDescription(void) {
|
||||
META_DLLAPI_HANDLE(const char *, NULL, FN_GETGAMEDESCRIPTION, pfnGetGameDescription, void, (VOID_ARG));
|
||||
RETURN_API(const char *);
|
||||
}
|
||||
static void mm_PlayerCustomization(edict_t *pEntity, customization_t *pCust) {
|
||||
META_DLLAPI_HANDLE_void(FN_PLAYERCUSTOMIZATION, pfnPlayerCustomization, 2p, (pEntity, pCust));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_SpectatorConnect(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_SPECTATORCONNECT, pfnSpectatorConnect, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_SpectatorDisconnect(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_SPECTATORDISCONNECT, pfnSpectatorDisconnect, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_SpectatorThink(edict_t *pEntity) {
|
||||
META_DLLAPI_HANDLE_void(FN_SPECTATORTHINK, pfnSpectatorThink, p, (pEntity));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_Sys_Error(const char *error_string) {
|
||||
META_DLLAPI_HANDLE_void(FN_SYS_ERROR, pfnSys_Error, p, (error_string));
|
||||
RETURN_API_void();
|
||||
}
|
||||
|
||||
// From SDK pm_shared/pm_shared.c:
|
||||
static void mm_PM_Move (struct playermove_s *ppmove, int server) {
|
||||
META_DLLAPI_HANDLE_void(FN_PM_MOVE, pfnPM_Move, pi, (ppmove, server));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_PM_Init(struct playermove_s *ppmove) {
|
||||
META_DLLAPI_HANDLE_void(FN_PM_INIT, pfnPM_Init, p, (ppmove));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static char mm_PM_FindTextureType(char *name) {
|
||||
META_DLLAPI_HANDLE(char, '\0', FN_PM_FINDTEXTURETYPE, pfnPM_FindTextureType, p, (name));
|
||||
RETURN_API(char);
|
||||
}
|
||||
|
||||
// From SDK dlls/client.cpp:
|
||||
static void mm_SetupVisibility(edict_t *pViewEntity, edict_t *pClient, unsigned char **pvs, unsigned char **pas) {
|
||||
META_DLLAPI_HANDLE_void(FN_SETUPVISIBILITY, pfnSetupVisibility, 4p, (pViewEntity, pClient, pvs, pas));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_UpdateClientData (const struct edict_s *ent, int sendweapons, struct clientdata_s *cd) {
|
||||
META_DLLAPI_HANDLE_void(FN_UPDATECLIENTDATA, pfnUpdateClientData, pip, (ent, sendweapons, cd));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static int mm_AddToFullPack(struct entity_state_s *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet) {
|
||||
META_DLLAPI_HANDLE(int, 0, FN_ADDTOFULLPACK, pfnAddToFullPack, pi2p2ip, (state, e, ent, host, hostflags, player, pSet));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static void mm_CreateBaseline(int player, int eindex, struct entity_state_s *baseline, struct edict_s *entity, int playermodelindex, vec3_t player_mins, vec3_t player_maxs) {
|
||||
META_DLLAPI_HANDLE_void(FN_CREATEBASELINE, pfnCreateBaseline, 2i2pi2p, (player, eindex, baseline, entity, playermodelindex, (float*)player_mins, (float*)player_maxs));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_RegisterEncoders(void) {
|
||||
META_DLLAPI_HANDLE_void(FN_REGISTERENCODERS, pfnRegisterEncoders, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static int mm_GetWeaponData(struct edict_s *player, struct weapon_data_s *info) {
|
||||
META_DLLAPI_HANDLE(int, 0, FN_GETWEAPONDATA, pfnGetWeaponData, 2p, (player, info));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static void mm_CmdStart(const edict_t *player, const struct usercmd_s *cmd, unsigned int random_seed) {
|
||||
META_DLLAPI_HANDLE_void(FN_CMDSTART, pfnCmdStart, 2pui, (player, cmd, random_seed));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_CmdEnd (const edict_t *player) {
|
||||
META_DLLAPI_HANDLE_void(FN_CMDEND, pfnCmdEnd, p, (player));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static int mm_ConnectionlessPacket(const struct netadr_s *net_from, const char *args, char *response_buffer, int *response_buffer_size) {
|
||||
META_DLLAPI_HANDLE(int, 0, FN_CONNECTIONLESSPACKET, pfnConnectionlessPacket, 4p, (net_from, args, response_buffer, response_buffer_size));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static int mm_GetHullBounds(int hullnumber, float *mins, float *maxs) {
|
||||
META_DLLAPI_HANDLE(int, 0, FN_GETHULLBOUNDS, pfnGetHullBounds, i2p, (hullnumber, mins, maxs));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static void mm_CreateInstancedBaselines (void) {
|
||||
META_DLLAPI_HANDLE_void(FN_CREATEINSTANCEDBASELINES, pfnCreateInstancedBaselines, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static int mm_InconsistentFile(const edict_t *player, const char *filename, char *disconnect_message) {
|
||||
META_DLLAPI_HANDLE(int, 0, FN_INCONSISTENTFILE, pfnInconsistentFile, 3p, (player, filename, disconnect_message));
|
||||
RETURN_API(int);
|
||||
}
|
||||
static int mm_AllowLagCompensation(void) {
|
||||
META_DLLAPI_HANDLE(int, 0, FN_ALLOWLAGCOMPENSATION, pfnAllowLagCompensation, void, (VOID_ARG));
|
||||
RETURN_API(int);
|
||||
}
|
||||
|
||||
|
||||
// New API functions
|
||||
// From SDK ?
|
||||
static void mm_OnFreeEntPrivateData(edict_t *pEnt) {
|
||||
META_NEWAPI_HANDLE_void(FN_ONFREEENTPRIVATEDATA, pfnOnFreeEntPrivateData, p, (pEnt));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static void mm_GameShutdown(void) {
|
||||
META_NEWAPI_HANDLE_void(FN_GAMESHUTDOWN, pfnGameShutdown, void, (VOID_ARG));
|
||||
RETURN_API_void();
|
||||
}
|
||||
static int mm_ShouldCollide(edict_t *pentTouched, edict_t *pentOther) {
|
||||
META_NEWAPI_HANDLE(int, 1, FN_SHOULDCOLLIDE, pfnShouldCollide, 2p, (pentTouched, pentOther));
|
||||
RETURN_API(int);
|
||||
}
|
||||
// Added 2005/08/11 (no SDK update):
|
||||
static void mm_CvarValue(const edict_t *pEnt, const char *value) {
|
||||
g_Players.clear_player_cvar_query(pEnt);
|
||||
META_NEWAPI_HANDLE_void(FN_CVARVALUE, pfnCvarValue, 2p, (pEnt, value));
|
||||
|
||||
RETURN_API_void();
|
||||
}
|
||||
// Added 2005/11/21 (no SDK update):
|
||||
static void mm_CvarValue2(const edict_t *pEnt, int requestID, const char *cvarName, const char *value) {
|
||||
META_NEWAPI_HANDLE_void(FN_CVARVALUE2, pfnCvarValue2, pi2p, (pEnt, requestID, cvarName, value));
|
||||
|
||||
RETURN_API_void();
|
||||
}
|
||||
|
||||
|
||||
// From SDK dlls/cbase.cpp:
|
||||
// "(wd)" indicates my comments on the functions
|
||||
static DLL_FUNCTIONS gFunctionTable =
|
||||
{
|
||||
mm_GameDLLInit, //! pfnGameInit() Initialize the game (one-time call after loading of game .dll)
|
||||
mm_DispatchSpawn, //! pfnSpawn()
|
||||
mm_DispatchThink, //! pfnThink()
|
||||
mm_DispatchUse, //! pfnUse()
|
||||
mm_DispatchTouch, //! pfnTouch()
|
||||
mm_DispatchBlocked, //! pfnBlocked()
|
||||
mm_DispatchKeyValue, //! pfnKeyValue()
|
||||
mm_DispatchSave, //! pfnSave()
|
||||
mm_DispatchRestore, //! pfnRestore()
|
||||
mm_DispatchObjectCollsionBox, //! pfnSetAbsBox()
|
||||
|
||||
mm_SaveWriteFields, //! pfnSaveWriteFields()
|
||||
mm_SaveReadFields, //! pfnSaveReadFields()
|
||||
|
||||
mm_SaveGlobalState, //! pfnSaveGlobalState()
|
||||
mm_RestoreGlobalState, //! pfnRestoreGlobalState()
|
||||
mm_ResetGlobalState, //! pfnResetGlobalState()
|
||||
|
||||
mm_ClientConnect, //! pfnClientConnect() (wd) Client has connected
|
||||
mm_ClientDisconnect, //! pfnClientDisconnect() (wd) Player has left the game
|
||||
mm_ClientKill, //! pfnClientKill() (wd) Player has typed "kill"
|
||||
mm_ClientPutInServer, //! pfnClientPutInServer() (wd) Client is entering the game
|
||||
mm_ClientCommand, //! pfnClientCommand() (wd) Player has sent a command (typed, or from a bind)
|
||||
mm_ClientUserInfoChanged, //! pfnClientUserInfoChanged() (wd) Client has updated their setinfo structure
|
||||
mm_ServerActivate, //! pfnServerActivate() (wd) Server is starting a new map
|
||||
mm_ServerDeactivate, //! pfnServerDeactivate() (wd) Server is leaving the map (shutdown, or changelevel); SDK2
|
||||
|
||||
mm_PlayerPreThink, //! pfnPlayerPreThink()
|
||||
mm_PlayerPostThink, //! pfnPlayerPostThink()
|
||||
|
||||
mm_StartFrame, //! pfnStartFrame()
|
||||
mm_ParmsNewLevel, //! pfnParmsNewLevel()
|
||||
mm_ParmsChangeLevel, //! pfnParmsChangeLevel()
|
||||
|
||||
mm_GetGameDescription, //! pfnGetGameDescription() Returns string describing current .dll. E.g. "TeamFotrress 2", "Half-Life"
|
||||
mm_PlayerCustomization, //! pfnPlayerCustomization() Notifies .dll of new customization for player.
|
||||
|
||||
mm_SpectatorConnect, //! pfnSpectatorConnect() Called when spectator joins server
|
||||
mm_SpectatorDisconnect, //! pfnSpectatorDisconnect() Called when spectator leaves the server
|
||||
mm_SpectatorThink, //! pfnSpectatorThink() Called when spectator sends a command packet (usercmd_t)
|
||||
|
||||
mm_Sys_Error, //! pfnSys_Error() Notify game .dll that engine is going to shut down. Allows mod authors to set a breakpoint. SDK2
|
||||
|
||||
mm_PM_Move, //! pfnPM_Move() (wd) SDK2
|
||||
mm_PM_Init, //! pfnPM_Init() Server version of player movement initialization; (wd) SDK2
|
||||
mm_PM_FindTextureType, //! pfnPM_FindTextureType() (wd) SDK2
|
||||
|
||||
mm_SetupVisibility, //! pfnSetupVisibility() Set up PVS and PAS for networking for this client; (wd) SDK2
|
||||
mm_UpdateClientData, //! pfnUpdateClientData() Set up data sent only to specific client; (wd) SDK2
|
||||
mm_AddToFullPack, //! pfnAddToFullPack() (wd) SDK2
|
||||
mm_CreateBaseline, //! pfnCreateBaseline() Tweak entity baseline for network encoding, allows setup of player baselines, too.; (wd) SDK2
|
||||
mm_RegisterEncoders, //! pfnRegisterEncoders() Callbacks for network encoding; (wd) SDK2
|
||||
mm_GetWeaponData, //! pfnGetWeaponData() (wd) SDK2
|
||||
mm_CmdStart, //! pfnCmdStart() (wd) SDK2
|
||||
mm_CmdEnd, //! pfnCmdEnd() (wd) SDK2
|
||||
mm_ConnectionlessPacket, //! pfnConnectionlessPacket() (wd) SDK2
|
||||
mm_GetHullBounds, //! pfnGetHullBounds() (wd) SDK2
|
||||
mm_CreateInstancedBaselines, //! pfnCreateInstancedBaselines() (wd) SDK2
|
||||
mm_InconsistentFile, //! pfnInconsistentFile() (wd) SDK2
|
||||
mm_AllowLagCompensation, //! pfnAllowLagCompensation() (wd) SDK2
|
||||
};
|
||||
|
||||
DLL_FUNCTIONS *g_pHookedDllFunctions = &gFunctionTable;
|
||||
|
||||
// It's not clear what the difference is between GetAPI and GetAPI2; they
|
||||
// both appear to return the exact same function table.
|
||||
//
|
||||
// Only one of them appears to be ever called, though. If the DLL provides
|
||||
// GetAPI2, the engine/hlds will call that, and will not call GetAPI. If
|
||||
// the engine couldn't find GetAPI2 in the DLL, it appears to fall back to
|
||||
// GetAPI.
|
||||
//
|
||||
// So, GetAPI2 appears to replace GetAPI, and appears to have been added
|
||||
// with SDK 2.0. My best guess is that, with the new SDK, interface
|
||||
// version checking became important, and without the int ptr used in
|
||||
// GetAPI2, the engine can't find out the version of the DLL via GetAPI.
|
||||
//
|
||||
// It's unclear whether a DLL coded under SDK2 needs to provide the older
|
||||
// GetAPI or not..
|
||||
|
||||
C_DLLEXPORT int GetEntityAPI(DLL_FUNCTIONS *pFunctionTable, int interfaceVersion)
|
||||
{
|
||||
META_DEBUG(3, ("called: GetEntityAPI; version=%d", interfaceVersion));
|
||||
if(!pFunctionTable || metamod_not_loaded) {
|
||||
META_WARNING("GetEntityAPI called with null pFunctionTable");
|
||||
return(FALSE);
|
||||
}
|
||||
else if(interfaceVersion != INTERFACE_VERSION) {
|
||||
META_WARNING("GetEntityAPI version mismatch; requested=%d ours=%d", interfaceVersion, INTERFACE_VERSION);
|
||||
return(FALSE);
|
||||
}
|
||||
memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS));
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
C_DLLEXPORT int GetEntityAPI2(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion)
|
||||
{
|
||||
META_DEBUG(3, ("called: GetEntityAPI2; version=%d", *interfaceVersion));
|
||||
if(!pFunctionTable || metamod_not_loaded) {
|
||||
META_WARNING("GetEntityAPI2 called with null pFunctionTable");
|
||||
return(FALSE);
|
||||
}
|
||||
else if(*interfaceVersion != INTERFACE_VERSION) {
|
||||
META_WARNING("GetEntityAPI2 version mismatch; requested=%d ours=%d", *interfaceVersion, INTERFACE_VERSION);
|
||||
//! Tell engine what version we had, so it can figure out who is out of date.
|
||||
*interfaceVersion = INTERFACE_VERSION;
|
||||
return(FALSE);
|
||||
}
|
||||
memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS));
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
||||
// I could find _no_ documentation or examples for the intended use of
|
||||
// NEW_DLL_FUNCTIONS. I wouldn't have even _known_ about the
|
||||
// GetNewDLLFunctions() function except for the reference in Adminmod.. It
|
||||
// appears to be new with SDK 2.0.
|
||||
//
|
||||
// Obviously, it seems to provide additional functions to the engine, but
|
||||
// it's unclear why a new table and interface were added, rather than
|
||||
// appending new functions to the GetAPI table/interface.
|
||||
//
|
||||
// Interestingly, it appears to be called by the engine _before_ GetAPI.
|
||||
|
||||
static meta_new_dll_functions_t sNewFunctionTable(
|
||||
&mm_OnFreeEntPrivateData, //! pfnOnFreeEntPrivateData() Called right before the object's memory is freed. Calls its destructor.
|
||||
&mm_GameShutdown, //! pfnGameShutdown()
|
||||
&mm_ShouldCollide, //! pfnShouldCollide()
|
||||
// Added 2005/08/11 (no SDK update):
|
||||
&mm_CvarValue, //! pfnCvarValue()
|
||||
// Added 2005/11/21 (no SDK update):
|
||||
&mm_CvarValue2 //! pfnCvarValue2()
|
||||
);
|
||||
|
||||
NEW_DLL_FUNCTIONS *g_pHookedNewDllFunctions = &sNewFunctionTable;
|
||||
|
||||
C_DLLEXPORT int GetNewDLLFunctions(NEW_DLL_FUNCTIONS *pNewFunctionTable, int *interfaceVersion)
|
||||
{
|
||||
META_DEBUG(6, ("called: GetNewDLLFunctions; version=%d", *interfaceVersion));
|
||||
#if 0 // ~dvander - but then you can't use cvar querying on many mods...
|
||||
// Don't provide these functions to engine if gamedll doesn't provide
|
||||
// them. Otherwise, we're in the position of having to provide answers
|
||||
// we can't necessarily provide (for instance, ShouldCollide())...
|
||||
if(!GameDLL.funcs.newapi_table)
|
||||
return(FALSE);
|
||||
#endif
|
||||
|
||||
if(!pNewFunctionTable) {
|
||||
META_ERROR("GetNewDLLFunctions called with null pNewFunctionTable");
|
||||
return(FALSE);
|
||||
}
|
||||
else if(*interfaceVersion != NEW_DLL_FUNCTIONS_VERSION) {
|
||||
META_ERROR("GetNewDLLFunctions version mismatch; requested=%d ours=%d", *interfaceVersion, NEW_DLL_FUNCTIONS_VERSION);
|
||||
//! Tell engine what version we had, so it can figure out who is out of date.
|
||||
*interfaceVersion = NEW_DLL_FUNCTIONS_VERSION;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
sNewFunctionTable.copy_to(pNewFunctionTable);
|
||||
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -37,6 +37,7 @@
|
||||
#ifndef ENGINE_API_H
|
||||
#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 );
|
||||
|
||||
@@ -1,390 +0,0 @@
|
||||
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// engineinfo.cpp - get info about HL engine, like file used
|
||||
// and test segment range
|
||||
//
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
// Don't include winspool.h; clashes with SERVER_EXECUTE from engine
|
||||
# define _WINSPOOL_H
|
||||
# include <windows.h>
|
||||
# include <winnt.h> // Header structures
|
||||
#else
|
||||
# ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
# endif
|
||||
# include <dlfcn.h> // dladdr()
|
||||
# include <link.h> // ElfW(Phdr/Ehdr) macros.
|
||||
// _DYNAMIC, r_debug, link_map, etc.
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include <string.h> // strlen(), strrchr(), strcmp()
|
||||
#include <stdio.h> // printf()
|
||||
|
||||
#include "engineinfo.h" // me
|
||||
#include "log_meta.h" // META_DEV()
|
||||
|
||||
|
||||
// Current mask for checking engine function addresses
|
||||
// in VAC protected engine dlls on Win32. This is gonna fail
|
||||
// on Win64.
|
||||
const unsigned long c_VacDllEngineFuncsRangeMask = 0xFFF00000;
|
||||
const unsigned long c_VacDllEngineFuncsRangeMark = 0x01D00000;
|
||||
void* const c_VacDllEngineFuncsRangeStart = (void*)0x01D00000;
|
||||
void* const c_VacDllEngineFuncsRangeEnd = (void*)0x01E00000;
|
||||
|
||||
|
||||
bool DLLINTERNAL EngineInfo::check_for_engine_module( const char* _pName )
|
||||
{
|
||||
const char* pC;
|
||||
size_t size;
|
||||
|
||||
if ( NULL == _pName ) return false;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// The engine module is either sw.dll or hw.dll or swds.dll
|
||||
pC = strrchr( _pName, '.' );
|
||||
|
||||
pC -= 2;
|
||||
if ( 0 != strcmp(pC, "sw.dll") && 0 != strcmp(pC, "hw.dll") ) {
|
||||
pC -= 2;
|
||||
if ( 0 != strcmp(pC, "swds.dll") ) return false;
|
||||
}
|
||||
|
||||
HMODULE hModule = GetModuleHandle( pC );
|
||||
if ( NULL == hModule ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ok, we found the string sw(ds).dll, thus we deduct that this is the
|
||||
// name of the engine's shared object. We copy the string for future
|
||||
// reference and return successfully.
|
||||
size = 0;
|
||||
while ( *pC != '.' && size < c_EngineInfo__typeLen-1 ) {
|
||||
m_type[size++] = *pC++;
|
||||
}
|
||||
m_type[size] = '\0';
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
const char* pType;
|
||||
|
||||
|
||||
size = strlen( _pName );
|
||||
if ( size < 11 ) {
|
||||
// Forget it, this string is too short to even be 'engine_.so', so
|
||||
// it can't the name of the engine shared library.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start parsing at the end. Since we know that the string is at least
|
||||
// 11 characters long we can safely do our parsing without being afraid
|
||||
// of leaving the string.
|
||||
pC = _pName + size -1;
|
||||
|
||||
// First we see if the string ends in '.so'
|
||||
if ( *pC-- != 'o' || *pC-- != 's' || *pC-- != '.' ) return false;
|
||||
|
||||
// Now find the '_' which would be the seperator between 'engine' and
|
||||
// the architecture.
|
||||
while ( *pC != '_' && pC != _pName ) --pC;
|
||||
if ( pC == _pName ) return false;
|
||||
|
||||
// We are at the '_', thus the architecture identifier must start at
|
||||
// the next character.
|
||||
pType = pC +1;
|
||||
|
||||
// Now we walk further back and check if we find the string 'engine'
|
||||
// backwards.
|
||||
--pC;
|
||||
if ( *pC-- != 'e' || *pC-- != 'n' || *pC-- != 'i' ||
|
||||
*pC-- != 'g' || *pC-- != 'n' || *pC != 'e' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ok, we found the string engine_*.so, thus we deduct that this is the
|
||||
// name of the engine's shared object. We copy the architecture string
|
||||
// for future reference and return successfully.
|
||||
size = 0;
|
||||
while ( *pType != '.' && size < c_EngineInfo__typeLen-1 ) {
|
||||
m_type[size++] = *pType++;
|
||||
}
|
||||
m_type[size] = '\0';
|
||||
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
int DLLINTERNAL EngineInfo::nthdr_module_name( void )
|
||||
{
|
||||
PIMAGE_DOS_HEADER pDosHeader;
|
||||
PIMAGE_NT_HEADERS pNTHeader;
|
||||
unsigned char* pBaseAddr;
|
||||
const char* pName = "sw.dll";
|
||||
|
||||
if ( ! check_for_engine_module(pName) ) {
|
||||
pName = "hw.dll";
|
||||
if ( ! check_for_engine_module(pName) ) {
|
||||
pName = "swds.dll";
|
||||
if ( ! check_for_engine_module(pName) ) {
|
||||
return MODULE_NAME_NOTFOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get the module handle for the engine dll we found.
|
||||
// This is also the modules base address.
|
||||
HMODULE hModule = GetModuleHandle( pName );
|
||||
|
||||
pBaseAddr = (unsigned char*)hModule;
|
||||
|
||||
|
||||
// Check if we find a DOS header
|
||||
pDosHeader = (PIMAGE_DOS_HEADER)hModule;
|
||||
if ( pDosHeader->e_magic != IMAGE_DOS_SIGNATURE ) {
|
||||
return INVALID_DOS_SIGN;
|
||||
}
|
||||
|
||||
// Check if we find a PE header
|
||||
pNTHeader = (PIMAGE_NT_HEADERS)(pBaseAddr + pDosHeader->e_lfanew);
|
||||
if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE ) {
|
||||
return INVALID_NT_SIGN;
|
||||
}
|
||||
|
||||
set_code_range( pBaseAddr, pNTHeader );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int DLLINTERNAL EngineInfo::vac_pe_approx( enginefuncs_t* _pFuncs )
|
||||
{
|
||||
if ( NULL == _pFuncs ) return INVALID_ARG;
|
||||
|
||||
// There is really no good and easy way to do this. Right now what
|
||||
// we do is assume that Steam listenservers will normally be
|
||||
// up-to-date and hence have all function pointers set correctly.
|
||||
// So we just check for some anomality and then set some approximated
|
||||
// values.
|
||||
|
||||
// The known addresses at the time of writing all start with 0x01D and
|
||||
// this lie in the range between 0x01D00000 and 0x01E00000. What we do
|
||||
// is check all functions pointers that are known to be good to start
|
||||
// with 0x01D. If that is the case then we know that the loading address
|
||||
// of the engine functions hasn't changed and we assume the above stated
|
||||
// range to be the range of valid engine function addresses.
|
||||
// If we find functions outside this range we can't determine a valid
|
||||
// range and have to just give up.
|
||||
|
||||
unsigned long* pengfuncs = (unsigned long*)_pFuncs;
|
||||
unsigned int i, invals = 0;
|
||||
for ( i = 0, pengfuncs += i; i < 140; i++, pengfuncs++ ) {
|
||||
if ( ((*pengfuncs) & c_VacDllEngineFuncsRangeMask) != c_VacDllEngineFuncsRangeMark ) {
|
||||
invals++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( invals > 0 ) {
|
||||
META_DEV( "Found %d engine functions out of range 0x%08lx. "
|
||||
"Unable to determine valid engine code address range.",
|
||||
invals, c_VacDllEngineFuncsRangeMark );
|
||||
|
||||
strncpy( m_type, "vacdll+?", c_EngineInfo__typeLen );
|
||||
m_state = STATE_INVALID;
|
||||
return STATE_INVALID;
|
||||
}
|
||||
|
||||
m_codeStart = c_VacDllEngineFuncsRangeStart;
|
||||
m_codeEnd = c_VacDllEngineFuncsRangeEnd;
|
||||
|
||||
strncpy( m_type, "vacdll", c_EngineInfo__typeLen );
|
||||
|
||||
m_state = STATE_VALID;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void DLLINTERNAL EngineInfo::set_code_range( unsigned char* _pBase, PIMAGE_NT_HEADERS _pNThdr )
|
||||
{
|
||||
m_codeStart = _pBase + _pNThdr->OptionalHeader.BaseOfCode;
|
||||
m_codeEnd = _pBase + _pNThdr->OptionalHeader.BaseOfCode + _pNThdr->OptionalHeader.SizeOfCode;
|
||||
|
||||
m_state = STATE_VALID;
|
||||
}
|
||||
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
|
||||
int DLLINTERNAL EngineInfo::phdr_elfhdr( void* _pElfHdr )
|
||||
{
|
||||
ElfW(Ehdr)* pEhdr = (ElfW(Ehdr)*)_pElfHdr;
|
||||
ElfW(Phdr)* pPhdr;
|
||||
|
||||
if ( NULL == _pElfHdr ) return INVALID_ARG;
|
||||
|
||||
if ( pEhdr->e_ident[0] == 0x7f
|
||||
&& pEhdr->e_ident[1] == 'E'
|
||||
&& pEhdr->e_ident[2] == 'L'
|
||||
&& pEhdr->e_ident[3] == 'F' ) {
|
||||
|
||||
// Looking good, we found an ELF signature.
|
||||
// Let's see if the rest of the data at this address would fit an ELH header, too.
|
||||
if ( (pEhdr->e_ident[EI_CLASS] == ELFCLASS32 //ELFW(CLASS)
|
||||
|| pEhdr->e_ident[EI_CLASS] == ELFCLASS64)
|
||||
|
||||
&& (pEhdr->e_ident[EI_DATA] == ELFDATA2LSB
|
||||
|| pEhdr->e_ident[EI_DATA] == ELFDATA2MSB)
|
||||
|
||||
&& pEhdr->e_type == ET_DYN ) {
|
||||
|
||||
// Ok, we believe that this is a shared object's ELF header.
|
||||
// Let's find the program header for the segment that includes
|
||||
// the text section and return it.
|
||||
|
||||
pPhdr = (ElfW(Phdr) *) ((char *) pEhdr + pEhdr->e_phoff);
|
||||
for ( int i = 0; i < pEhdr->e_phnum; i++, pPhdr++ ) {
|
||||
|
||||
if ( PT_LOAD == pPhdr->p_type
|
||||
&& (pPhdr->p_flags & PF_R)
|
||||
&& (pPhdr->p_flags & PF_X) ) {
|
||||
|
||||
// The text section gets loaded and has read and
|
||||
// execute flags set. So this must be it.
|
||||
set_code_range( pEhdr, pPhdr );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HEADER_NOTFOUND;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int DLLINTERNAL EngineInfo::phdr_dladdr( void* _pMem )
|
||||
{
|
||||
Dl_info info;
|
||||
|
||||
if ( 0 != dladdr(_pMem, &info) ) {
|
||||
// Check if this is the engine module
|
||||
if ( check_for_engine_module(info.dli_fname) ) {
|
||||
return phdr_elfhdr( info.dli_fbase );
|
||||
}
|
||||
}
|
||||
|
||||
return NOTFOUND;
|
||||
}
|
||||
|
||||
|
||||
int DLLINTERNAL EngineInfo::phdr_r_debug( void )
|
||||
{
|
||||
ElfW(Dyn)* pDyn;
|
||||
struct r_debug* pr_debug;
|
||||
struct link_map* pMap;
|
||||
|
||||
|
||||
// Search if we have a DT_DEBUG symbol in our DYNAMIC segment, which
|
||||
// ought to be set to the r_debug structure's address.
|
||||
for (pDyn = _DYNAMIC; pDyn->d_tag != DT_NULL; ++pDyn) {
|
||||
if (pDyn->d_tag == DT_DEBUG) {
|
||||
pr_debug = (struct r_debug *) pDyn->d_un.d_ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( DT_NULL == pDyn->d_tag ) {
|
||||
}
|
||||
else if ( NULL == pr_debug ) {
|
||||
}
|
||||
else {
|
||||
pMap = pr_debug->r_map;
|
||||
|
||||
// Walk to the start of the list
|
||||
while ( pMap->l_prev != NULL ) pMap = pMap->l_prev;
|
||||
do {
|
||||
if ( check_for_engine_module(pMap->l_name) ) {
|
||||
return phdr_elfhdr( (void*)pMap->l_addr );
|
||||
}
|
||||
|
||||
pMap = pMap->l_next;
|
||||
} while ( NULL != pMap );
|
||||
|
||||
}
|
||||
|
||||
return NOTFOUND;
|
||||
}
|
||||
|
||||
void DLLINTERNAL EngineInfo::set_code_range( void* _pBase, ElfW(Phdr)* _pPhdr )
|
||||
{
|
||||
unsigned char* pBase = (unsigned char*)_pBase;
|
||||
m_codeStart = pBase + _pPhdr->p_vaddr;
|
||||
m_codeEnd = pBase + _pPhdr->p_vaddr + _pPhdr->p_memsz;
|
||||
|
||||
m_state = STATE_VALID;
|
||||
}
|
||||
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
||||
int DLLINTERNAL EngineInfo::initialise( enginefuncs_t* _pFuncs )
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
// Have to do this only once.
|
||||
if ( NULL != m_codeStart ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
ret = nthdr_module_name();
|
||||
if ( MODULE_NAME_NOTFOUND == ret && (! _pFuncs->pfnIsDedicatedServer()) ) {
|
||||
// We could not find the engine dll by name and we are running on
|
||||
// a listen server. This usually means that that we are dealing with
|
||||
// a VAC protected engine dll. No other way than approximating the
|
||||
// range of valid engine function pointers in this case.
|
||||
ret = vac_pe_approx( _pFuncs );
|
||||
}
|
||||
|
||||
#else /* _WIN32 */
|
||||
|
||||
// If we have no reference pointer to start from we can only try to use
|
||||
// the r_debug symbol.
|
||||
if ( NULL == _pFuncs ) {
|
||||
ret = phdr_r_debug();
|
||||
}
|
||||
|
||||
// If we have a refererence pointer we try to use it first.
|
||||
if ( 0 != phdr_dladdr(_pFuncs) ) {
|
||||
ret = phdr_r_debug();
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
if ( 0 != ret ) {
|
||||
META_DEV( "Unable to determine engine code address range!" );
|
||||
}
|
||||
else {
|
||||
META_DEV( "Set engine code range: start address = %p, end address = %p",
|
||||
m_codeStart, m_codeEnd );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// autodetect.cpp - GameDLL search and autodetection.
|
||||
|
||||
/*
|
||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
||||
*
|
||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <extdll.h> // always
|
||||
#include "osdep_p.h" // is_gamedll, ...
|
||||
#include "game_autodetect.h" // me
|
||||
#include "support_meta.h" // full_gamedir_path,
|
||||
|
||||
|
||||
// Search gamedir/dlls/*.dll for gamedlls
|
||||
//TODO: add META_DEBUG
|
||||
const char * DLLINTERNAL autodetect_gamedll(const gamedll_t *gamedll, const char *knownfn)
|
||||
{
|
||||
static char buf[256];
|
||||
char dllpath[256];
|
||||
char fnpath[256];
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
unsigned int fn_len;
|
||||
|
||||
// Generate dllpath
|
||||
safevoid_snprintf(buf, sizeof(buf), "%s/dlls", gamedll->gamedir);
|
||||
if(!full_gamedir_path(buf, dllpath)) {
|
||||
//whine & return
|
||||
META_WARNING("GameDLL-Autodetection: Directory '%s' doesn't exist.", buf);
|
||||
return(0);
|
||||
}
|
||||
|
||||
// Generate knownfn path
|
||||
safevoid_snprintf(fnpath, sizeof(fnpath), "%s/%s", dllpath, knownfn);
|
||||
|
||||
// Check if knownfn exists and is valid gamedll
|
||||
if(is_gamedll(fnpath)) {
|
||||
// knownfn exists and is loadable gamedll, return 0.
|
||||
return(0);
|
||||
}
|
||||
|
||||
// Open directory
|
||||
if(!(dir = opendir(dllpath))) {
|
||||
//whine & return
|
||||
META_WARNING("GameDLL-Autodetection: Couldn't open directory '%s'.", dllpath);
|
||||
return(0);
|
||||
}
|
||||
|
||||
while((ent = readdir(dir)) != 0) {
|
||||
fn_len = strlen(ent->d_name);
|
||||
|
||||
if(fn_len <= strlen(PLATFORM_DLEXT)) {
|
||||
// Filename is too short
|
||||
continue;
|
||||
}
|
||||
|
||||
// Compare end of filename with PLATFORM_DLEXT
|
||||
if(!strcasematch(&ent->d_name[fn_len - strlen(PLATFORM_DLEXT)], PLATFORM_DLEXT)) {
|
||||
// File isn't dll
|
||||
continue;
|
||||
}
|
||||
|
||||
// Exclude all metamods
|
||||
if(strncasematch(ent->d_name, "metamod", strlen("metamod"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Exclude all bots
|
||||
STRNCPY(buf, ent->d_name, sizeof(buf));
|
||||
strlwr(buf);
|
||||
if(strstr(buf, "bot.")) {
|
||||
continue;
|
||||
}
|
||||
#ifdef linux
|
||||
//bot_iX86.so, bot_amd64.so, bot_x86_64.so
|
||||
if(strstr(buf, "bot_i") || strstr(buf, "bot_amd64.so") || strstr(buf, "bot_x86")) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Generate full path
|
||||
safevoid_snprintf(fnpath, sizeof(fnpath), "%s/%s", dllpath, ent->d_name);
|
||||
|
||||
// Check if dll is gamedll
|
||||
if(is_gamedll(fnpath)) {
|
||||
META_DEBUG(8, ("is_gamedll(%s): ok.", fnpath));
|
||||
//gamedll detected
|
||||
STRNCPY(buf, ent->d_name, sizeof(buf));
|
||||
closedir(dir);
|
||||
return(buf);
|
||||
}
|
||||
META_DEBUG(8, ("is_gamedll(%s): failed.", fnpath));
|
||||
}
|
||||
|
||||
//not found
|
||||
META_WARNING("GameDLL-Autodetection: Couldn't find gamedll in '%s'.", dllpath);
|
||||
closedir(dir);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -1,331 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// game_support.cpp - info to recognize different HL mod "games"
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2013 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
#include <fcntl.h> // open, write
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "game_support.h" // me
|
||||
#include "log_meta.h" // META_LOG, etc
|
||||
#include "types_meta.h" // mBOOL
|
||||
#include "osdep.h" // win32 snprintf, etc
|
||||
#include "game_autodetect.h" // autodetect_gamedll
|
||||
#include "support_meta.h" // MIN
|
||||
|
||||
// Adapted from adminmod h_export.cpp:
|
||||
//! this structure contains a list of supported mods and their dlls names
|
||||
//! To add support for another mod add an entry here, and add all the
|
||||
//! exported entities to link_func.cpp
|
||||
const game_modlist_t known_games = {
|
||||
// name/gamedir linux_so win_dll desc
|
||||
//
|
||||
// Previously enumerated in this sourcefile, the list is now kept in a
|
||||
// separate file, generated based on game information stored in a
|
||||
// convenient db.
|
||||
//
|
||||
#include "games.h"
|
||||
// End of list terminator:
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
// Find a modinfo corresponding to the given game name.
|
||||
const game_modinfo_t * DLLINTERNAL lookup_game(const char *name) {
|
||||
const game_modinfo_t *imod;
|
||||
int i;
|
||||
for(i=0; known_games[i].name; i++) {
|
||||
imod=&known_games[i];
|
||||
if(strcasematch(imod->name, name))
|
||||
return(imod);
|
||||
}
|
||||
// no match found
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
// Installs gamedll from Steam cache
|
||||
mBOOL DLLINTERNAL install_gamedll(char *from, const char *to) {
|
||||
int length_in;
|
||||
int length_out;
|
||||
|
||||
if(!from)
|
||||
return mFALSE;
|
||||
if(!to)
|
||||
to = from;
|
||||
|
||||
byte* cachefile = LOAD_FILE_FOR_ME(from, &length_in);
|
||||
|
||||
// If the file seems to exist in the cache.
|
||||
if(cachefile) {
|
||||
int fd=open(to, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
|
||||
|
||||
if(fd < 0) {
|
||||
META_DEBUG(3, ("Installing gamedll from cache: Failed to create file %s: %s", to, strerror(errno)) );
|
||||
FREE_FILE(cachefile);
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
length_out=write(fd, cachefile, length_in);
|
||||
FREE_FILE(cachefile);
|
||||
close(fd);
|
||||
|
||||
// Writing the file was not successfull
|
||||
if(length_out != length_in) {
|
||||
META_DEBUG(3,("Installing gamedll from chache: Failed to write all %d bytes to file, only %d written: %s", length_in, length_out, strerror(errno)));
|
||||
// Let's not leave a mess but clean up nicely.
|
||||
if(length_out >= 0)
|
||||
unlink(to);
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
META_LOG("Installed gamedll %s from cache.", to);
|
||||
} else {
|
||||
META_DEBUG(3, ("Failed to install gamedll from cache: file %s not found in cache.", from) );
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
// Set all the fields in the gamedll struct, - based either on an entry in
|
||||
// known_games matching the current gamedir, or on one specified manually
|
||||
// by the server admin.
|
||||
//
|
||||
// meta_errno values:
|
||||
// - ME_NOTFOUND couldn't recognize game
|
||||
mBOOL DLLINTERNAL setup_gamedll(gamedll_t *gamedll) {
|
||||
#ifdef __x86_64__
|
||||
static char fixname_amd64[NAME_MAX]; // pointer is given outside function
|
||||
#endif
|
||||
static char override_desc_buf[NAME_MAX]; // pointer is given outside function
|
||||
static char autodetect_desc_buf[NAME_MAX]; // pointer is given outside function
|
||||
char install_path[NAME_MAX];
|
||||
const game_modinfo_t *known;
|
||||
char *cp, *strippedfn;
|
||||
const char *autofn = 0, *knownfn=0, *usedfn = 0;
|
||||
int override=0;
|
||||
|
||||
// Check for old-style "metagame.ini" file and complain.
|
||||
if(valid_gamedir_file(OLD_GAMEDLL_TXT))
|
||||
META_WARNING("File '%s' is no longer supported; instead, specify override gamedll in %s or with '+localinfo mm_gamedll <dllfile>'", OLD_GAMEDLL_TXT, CONFIG_INI);
|
||||
// First, look for a known game, based on gamedir.
|
||||
if((known=lookup_game(gamedll->name))) {
|
||||
#ifdef _WIN32
|
||||
knownfn=known->win_dll;
|
||||
#elif defined(linux)
|
||||
knownfn=known->linux_so;
|
||||
#ifdef __x86_64__
|
||||
//AMD64: convert _i386.so to _amd64.so
|
||||
if((cp = strstr(knownfn, "_i386.so")) ||
|
||||
(cp = strstr(knownfn, "_i486.so")) ||
|
||||
(cp = strstr(knownfn, "_i586.so")) ||
|
||||
(cp = strstr(knownfn, "_i686.so"))) {
|
||||
//make sure that it's the ending that has "_iX86.so"
|
||||
if(cp[strlen("_i386.so")] == 0) {
|
||||
STRNCPY(fixname_amd64, known->linux_so,
|
||||
MIN(((size_t)cp - (size_t)knownfn) + 1,
|
||||
sizeof(fixname_amd64)));
|
||||
strncat(fixname_amd64, "_amd64.so", sizeof(fixname_amd64));
|
||||
|
||||
knownfn=fixname_amd64;
|
||||
}
|
||||
}
|
||||
#endif /*__x86_64__*/
|
||||
#else
|
||||
#error "OS unrecognized"
|
||||
#endif /* _WIN32 */
|
||||
|
||||
// Do this before autodetecting gamedll from "dlls/*.dll"
|
||||
if(!Config->gamedll) {
|
||||
#ifdef linux
|
||||
// The engine changed game dll lookup behaviour in that it strips
|
||||
// anything after the last '_' from the name and tries to load the
|
||||
// resulting name. The DSO names were changed and do not have the
|
||||
// '_i386' part in them anymore, so cs_i386.so became cs.so. We
|
||||
// have to adapt to that and try to load the DSO name without the
|
||||
// '_*' part first, to see if we have a new version file available.
|
||||
char temp_str[NAME_MAX];
|
||||
|
||||
STRNCPY(temp_str, knownfn, sizeof(temp_str));
|
||||
strippedfn = temp_str;
|
||||
|
||||
char *loc = strrchr(strippedfn, '_');
|
||||
|
||||
// A small safety net here: make sure that we are dealing with
|
||||
// a file name at least four characters long and ending in
|
||||
// '.so'. This way we can be sure that we can safely overwrite
|
||||
// anything from the '_' on with '.so'.
|
||||
int size = 0;
|
||||
const char *ext;
|
||||
if(0 != loc) {
|
||||
size = strlen(strippedfn);
|
||||
ext = strippedfn + (size - 3);
|
||||
}
|
||||
|
||||
if(0 != loc && size > 3 && 0 == strcasecmp(ext, ".so")) {
|
||||
strcpy(loc, ".so");
|
||||
META_DEBUG(4, ("Checking for new version game DLL name '%s'.\n", strippedfn) );
|
||||
|
||||
// Again, as above, I abuse the real_pathname member to store the full pathname
|
||||
// and the pathname member to store the relative name to pass it to the
|
||||
// install_gamedll function to save stack space. They are going
|
||||
// to get overwritten later on, so that's ok.
|
||||
safevoid_snprintf(gamedll->pathname, sizeof(gamedll->pathname), "dlls/%s",
|
||||
strippedfn);
|
||||
// Check if the gamedll file exists. If not, try to install it from
|
||||
// the cache.
|
||||
mBOOL ok = mTRUE;
|
||||
if(!valid_gamedir_file(gamedll->pathname)) {
|
||||
safevoid_snprintf(gamedll->real_pathname, sizeof(gamedll->real_pathname), "%s/dlls/%s",
|
||||
gamedll->gamedir, strippedfn);
|
||||
ok = install_gamedll(gamedll->pathname, gamedll->real_pathname);
|
||||
}
|
||||
if(ok)
|
||||
usedfn = strippedfn;
|
||||
}
|
||||
else {
|
||||
META_DEBUG(4, ("Known game DLL name does not qualify for checking for a stripped version, skipping: '%s'.\n",
|
||||
strippedfn) );
|
||||
}
|
||||
#endif /* linux */
|
||||
// If no file to be used was found, try the old known DLL file
|
||||
// name.
|
||||
if (0 == usedfn) {
|
||||
META_DEBUG(4, ("Checking for old version game DLL name '%s'.\n", knownfn) );
|
||||
safevoid_snprintf(gamedll->pathname, sizeof(gamedll->pathname), "dlls/%s", knownfn);
|
||||
// Check if the gamedll file exists. If not, try to install it from
|
||||
// the cache.
|
||||
if(!valid_gamedir_file(gamedll->pathname)) {
|
||||
safevoid_snprintf(gamedll->real_pathname, sizeof(gamedll->real_pathname), "%s/dlls/%s",
|
||||
gamedll->gamedir, knownfn);
|
||||
install_gamedll(gamedll->pathname, gamedll->real_pathname);
|
||||
}
|
||||
} else {
|
||||
knownfn = usedfn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Then, autodetect gamedlls in "gamedir/dlls/"
|
||||
// autodetect_gamedll returns 0 if knownfn exists and is valid gamedll.
|
||||
if(Config->autodetect && (autofn=autodetect_gamedll(gamedll, knownfn))) {
|
||||
// If knownfn is set and autodetect_gamedll returns non-null
|
||||
// then knownfn doesn't exists and we should use autodetected
|
||||
// dll instead.
|
||||
if(knownfn) {
|
||||
// Whine loud about fact that known-list dll doesn't exists!
|
||||
//META_LOG(plapla);
|
||||
knownfn = autofn;
|
||||
}
|
||||
}
|
||||
|
||||
// Neither override nor known-list nor auto-detect found a gamedll.
|
||||
if(!known && !Config->gamedll && !autofn)
|
||||
RETURN_ERRNO(mFALSE, ME_NOTFOUND);
|
||||
|
||||
// Use override-dll if specified.
|
||||
if(Config->gamedll) {
|
||||
STRNCPY(gamedll->pathname, Config->gamedll,
|
||||
sizeof(gamedll->pathname));
|
||||
override=1;
|
||||
|
||||
// If the path is relative, the gamedll file will be missing and
|
||||
// it might be found in the cache file.
|
||||
if(!is_absolute_path(gamedll->pathname)) {
|
||||
safevoid_snprintf(install_path, sizeof(install_path),
|
||||
"%s/%s", gamedll->gamedir, gamedll->pathname);
|
||||
// If we could successfully install the gamedll from the cache we
|
||||
// rectify the pathname to be a full pathname.
|
||||
if(install_gamedll(gamedll->pathname, install_path))
|
||||
STRNCPY(gamedll->pathname, install_path, sizeof(gamedll->pathname));
|
||||
}
|
||||
}
|
||||
// Else use Known-list dll.
|
||||
else if(known) {
|
||||
safevoid_snprintf(gamedll->pathname, sizeof(gamedll->pathname), "%s/dlls/%s",
|
||||
gamedll->gamedir, knownfn);
|
||||
}
|
||||
// Else use Autodetect dll.
|
||||
else {
|
||||
safevoid_snprintf(gamedll->pathname, sizeof(gamedll->pathname), "%s/dlls/%s",
|
||||
gamedll->gamedir, autofn);
|
||||
}
|
||||
|
||||
// get filename from pathname
|
||||
cp=strrchr(gamedll->pathname, '/');
|
||||
if(cp)
|
||||
cp++;
|
||||
else
|
||||
cp=gamedll->pathname;
|
||||
gamedll->file=cp;
|
||||
|
||||
// If found, store also the supposed "real" dll path based on the
|
||||
// gamedir, in case it differs from the "override" dll path.
|
||||
if(known && override)
|
||||
safevoid_snprintf(gamedll->real_pathname, sizeof(gamedll->real_pathname),
|
||||
"%s/dlls/%s", gamedll->gamedir, knownfn);
|
||||
else if(known && autofn)
|
||||
safevoid_snprintf(gamedll->real_pathname, sizeof(gamedll->real_pathname),
|
||||
"%s/dlls/%s", gamedll->gamedir, knownfn);
|
||||
else // !known or (!override and !autofn)
|
||||
STRNCPY(gamedll->real_pathname, gamedll->pathname,
|
||||
sizeof(gamedll->real_pathname));
|
||||
|
||||
if(override) {
|
||||
// generate a desc
|
||||
safevoid_snprintf(override_desc_buf, sizeof(override_desc_buf), "%s (override)", gamedll->file);
|
||||
gamedll->desc=override_desc_buf;
|
||||
// log result
|
||||
META_LOG("Overriding game '%s' with dllfile '%s'", gamedll->name, gamedll->file);
|
||||
}
|
||||
else if(known && autofn) {
|
||||
// dll in known-list doesn't exists but we found new one with autodetect.
|
||||
|
||||
// generate a desc
|
||||
safevoid_snprintf(autodetect_desc_buf, sizeof(autodetect_desc_buf), "%s (autodetect-override)", gamedll->file);
|
||||
gamedll->desc=autodetect_desc_buf;
|
||||
META_LOG("Recognized game '%s'; Autodetection override; using dllfile '%s'", gamedll->name, gamedll->file);
|
||||
}
|
||||
else if(autofn) {
|
||||
// generate a desc
|
||||
safevoid_snprintf(autodetect_desc_buf, sizeof(autodetect_desc_buf), "%s (autodetect)", gamedll->file);
|
||||
gamedll->desc=autodetect_desc_buf;
|
||||
META_LOG("Autodetected game '%s'; using dllfile '%s'", gamedll->name, gamedll->file);
|
||||
}
|
||||
else if(known) {
|
||||
gamedll->desc=known->desc;
|
||||
META_LOG("Recognized game '%s'; using dllfile '%s'", gamedll->name, gamedll->file);
|
||||
}
|
||||
return(mTRUE);
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// h_export.cpp - main exported DLL functionality
|
||||
|
||||
// From SDK dlls/h_export.cpp:
|
||||
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
/*
|
||||
|
||||
===== h_export.cpp ========================================================
|
||||
|
||||
Entity classes exported by Halflife.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <extdll.h> // always
|
||||
#include <time.h>
|
||||
|
||||
#include "h_export.h" // me
|
||||
#include "metamod.h" // engine_t, etc
|
||||
#include "log_meta.h" // META_DEV, etc
|
||||
#include "osdep_p.h" // get_module_handle_of_memptr
|
||||
|
||||
// From SDK dlls/h_export.cpp:
|
||||
|
||||
#ifdef _WIN32
|
||||
//! Required DLL entry point
|
||||
// The above SDK comment indicates this routine is required, but the MSDN
|
||||
// documentation indicates it's actually optional. We keep it, though, for
|
||||
// completeness.
|
||||
// Note! 'extern "C"' needed for mingw compile.
|
||||
extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
if (fdwReason == DLL_PROCESS_ATTACH) {
|
||||
metamod_handle = hinstDLL;
|
||||
}
|
||||
else if (fdwReason == DLL_PROCESS_DETACH) {
|
||||
/* nothing */
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
#elif defined(linux)
|
||||
// Linux routines to correspond to ATTACH and DETACH cases above. These
|
||||
// aren't required by linux, but are included here for completeness, and
|
||||
// just in case we come across a need to do something at dll load or
|
||||
// unload.
|
||||
void _init(void) {
|
||||
// called before dlopen() returns
|
||||
}
|
||||
void _fini(void) {
|
||||
// called before dlclose() returns
|
||||
}
|
||||
#endif
|
||||
|
||||
// Fixed MSVC compiling, by Nikolay "The Storm" Baklicharov.
|
||||
#if defined(_WIN32) && !defined(__GNUC__) && defined (_MSC_VER)
|
||||
#pragma comment(linker, "/EXPORT:GiveFnptrsToDll=_GiveFnptrsToDll@8,@1")
|
||||
#pragma comment(linker, "/SECTION:.data,RW")
|
||||
#endif
|
||||
|
||||
//! Holds engine functionality callbacks
|
||||
HL_enginefuncs_t g_engfuncs;
|
||||
globalvars_t *gpGlobals;
|
||||
engine_t Engine;
|
||||
|
||||
// Receive engine function table from engine.
|
||||
//
|
||||
// This appears to be the _first_ DLL routine called by the engine, so this
|
||||
// is where we hook to load all the other DLLs (game, plugins, etc), which
|
||||
// is actually all done in meta_startup().
|
||||
C_DLLEXPORT void WINAPI GiveFnptrsToDll(enginefuncs_t *pengfuncsFromEngine,
|
||||
globalvars_t *pGlobals)
|
||||
{
|
||||
#ifdef linux
|
||||
metamod_handle = get_module_handle_of_memptr((void*)&g_engfuncs);
|
||||
#endif
|
||||
gpGlobals = pGlobals;
|
||||
Engine.funcs = &g_engfuncs;
|
||||
Engine.globals = pGlobals;
|
||||
Engine.info.initialise(pengfuncsFromEngine);
|
||||
|
||||
g_engfuncs.initialise_interface(pengfuncsFromEngine);
|
||||
// NOTE! Have to call logging function _after_ initialising g_engfuncs, so
|
||||
// that g_engfuncs.pfnAlertMessage() can be resolved properly, heh. :)
|
||||
META_DEV("called: GiveFnptrsToDll");
|
||||
|
||||
// Load plugins, load game dll.
|
||||
if(!metamod_startup()) {
|
||||
metamod_not_loaded = 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1,205 +0,0 @@
|
||||
/* Special ld script needed, because HL engine does some PE section checking on loaded gamedlls. */
|
||||
/* These checks fail and segfault HL process if default ld script is used! */
|
||||
OUTPUT_FORMAT(pei-i386)
|
||||
SEARCH_DIR("/mingw/mingw32/lib"); SEARCH_DIR("/mingw/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib");
|
||||
ENTRY(_mainCRTStartup)
|
||||
SECTIONS
|
||||
{
|
||||
.text __image_base__ + __section_alignment__ :
|
||||
{
|
||||
*(.init)
|
||||
*(.text)
|
||||
*(SORT(.text$*))
|
||||
*(.glue_7t)
|
||||
*(.glue_7)
|
||||
___CTOR_LIST__ = .; __CTOR_LIST__ = . ;
|
||||
LONG (-1);
|
||||
*(EXCLUDE_FILE (*crtend.o) .ctors);
|
||||
*(.ctor);
|
||||
*(SORT(.ctors.*));
|
||||
*crtend.o (.ctors);
|
||||
LONG (0);
|
||||
___DTOR_LIST__ = .; __DTOR_LIST__ = . ;
|
||||
LONG (-1);
|
||||
*(EXCLUDE_FILE (*crtend.o) .dtors);
|
||||
*(.dtor);
|
||||
*(SORT(.dtors.*));
|
||||
*crtend.o (.dtors);
|
||||
LONG (0);
|
||||
*(.fini)
|
||||
/* ??? Why is .gcc_exc here? */
|
||||
*(.gcc_exc)
|
||||
PROVIDE (etext = .);
|
||||
*(.gcc_except_table)
|
||||
/*}
|
||||
.rdata BLOCK(__section_alignment__) :
|
||||
{*/
|
||||
*(.rdata)
|
||||
*(SORT(.rdata$*))
|
||||
}
|
||||
/* The Cygwin32 library uses a section to avoid copying certain data
|
||||
on fork. This used to be named ".data". The linker used
|
||||
to include this between __data_start__ and __data_end__, but that
|
||||
breaks building the cygwin32 dll. Instead, we name the section
|
||||
".data_cygwin_nocopy" and explictly include it after __data_end__. */
|
||||
.data BLOCK(__section_alignment__) :
|
||||
{
|
||||
__data_start__ = . ;
|
||||
*(.data)
|
||||
*(.data2)
|
||||
*(SORT(.data$*))
|
||||
__data_end__ = . ;
|
||||
*(.data_cygwin_nocopy)
|
||||
*(.eh_frame)
|
||||
___RUNTIME_PSEUDO_RELOC_LIST__ = .;
|
||||
__RUNTIME_PSEUDO_RELOC_LIST__ = .;
|
||||
*(.rdata_runtime_pseudo_reloc)
|
||||
___RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
||||
__RUNTIME_PSEUDO_RELOC_LIST_END__ = .;
|
||||
/*}
|
||||
.bss BLOCK(__section_alignment__) :
|
||||
{*/
|
||||
__bss_start__ = . ;
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
__bss_end__ = . ;
|
||||
}
|
||||
.edata BLOCK(__section_alignment__) :
|
||||
{
|
||||
*(.edata)
|
||||
}
|
||||
.idata BLOCK(__section_alignment__) :
|
||||
{
|
||||
/* This cannot currently be handled with grouped sections.
|
||||
See pe.em:sort_sections. */
|
||||
SORT(*)(.idata$2)
|
||||
SORT(*)(.idata$3)
|
||||
/* These zeroes mark the end of the import list. */
|
||||
LONG (0); LONG (0); LONG (0); LONG (0); LONG (0);
|
||||
SORT(*)(.idata$4)
|
||||
SORT(*)(.idata$5)
|
||||
SORT(*)(.idata$6)
|
||||
SORT(*)(.idata$7)
|
||||
}
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.debug$S)
|
||||
*(.debug$T)
|
||||
*(.debug$F)
|
||||
*(.drectve)
|
||||
}
|
||||
.CRT BLOCK(__section_alignment__) :
|
||||
{
|
||||
___crt_xc_start__ = . ;
|
||||
*(SORT(.CRT$XC*)) /* C initialization */
|
||||
___crt_xc_end__ = . ;
|
||||
___crt_xi_start__ = . ;
|
||||
*(SORT(.CRT$XI*)) /* C++ initialization */
|
||||
___crt_xi_end__ = . ;
|
||||
___crt_xl_start__ = . ;
|
||||
*(SORT(.CRT$XL*)) /* TLS callbacks */
|
||||
/* ___crt_xl_end__ is defined in the TLS Directory support code */
|
||||
___crt_xp_start__ = . ;
|
||||
*(SORT(.CRT$XP*)) /* Pre-termination */
|
||||
___crt_xp_end__ = . ;
|
||||
___crt_xt_start__ = . ;
|
||||
*(SORT(.CRT$XT*)) /* Termination */
|
||||
___crt_xt_end__ = . ;
|
||||
}
|
||||
.tls BLOCK(__section_alignment__) :
|
||||
{
|
||||
___tls_start__ = . ;
|
||||
*(.tls)
|
||||
*(.tls$)
|
||||
*(SORT(.tls$*))
|
||||
___tls_end__ = . ;
|
||||
}
|
||||
.endjunk BLOCK(__section_alignment__) :
|
||||
{
|
||||
/* end is deprecated, don't use it */
|
||||
PROVIDE (end = .);
|
||||
PROVIDE ( _end = .);
|
||||
__end__ = .;
|
||||
}
|
||||
.rsrc BLOCK(__section_alignment__) :
|
||||
{
|
||||
*(.rsrc)
|
||||
*(SORT(.rsrc$*))
|
||||
}
|
||||
.reloc BLOCK(__section_alignment__) :
|
||||
{
|
||||
*(.reloc)
|
||||
}
|
||||
.stab BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.stab)
|
||||
}
|
||||
.stabstr BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.stabstr)
|
||||
}
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section. Unlike other targets that fake this by putting the
|
||||
section VMA at 0, the PE format will not allow it. */
|
||||
/* DWARF 1.1 and DWARF 2. */
|
||||
.debug_aranges BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_aranges)
|
||||
}
|
||||
.debug_pubnames BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_pubnames)
|
||||
}
|
||||
/* DWARF 2. */
|
||||
.debug_info BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_info) *(.gnu.linkonce.wi.*)
|
||||
}
|
||||
.debug_abbrev BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_abbrev)
|
||||
}
|
||||
.debug_line BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_line)
|
||||
}
|
||||
.debug_frame BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_frame)
|
||||
}
|
||||
.debug_str BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_str)
|
||||
}
|
||||
.debug_loc BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_loc)
|
||||
}
|
||||
.debug_macinfo BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_macinfo)
|
||||
}
|
||||
/* SGI/MIPS DWARF 2 extensions. */
|
||||
.debug_weaknames BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_weaknames)
|
||||
}
|
||||
.debug_funcnames BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_funcnames)
|
||||
}
|
||||
.debug_typenames BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_typenames)
|
||||
}
|
||||
.debug_varnames BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_varnames)
|
||||
}
|
||||
/* DWARF 3. */
|
||||
.debug_ranges BLOCK(__section_alignment__) (NOLOAD) :
|
||||
{
|
||||
*(.debug_ranges)
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// linkgame.cpp - export entities from mod "games" back to the HL engine
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
//linkents not needed on this version of metamod
|
||||
@@ -1,42 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// linkplug.cpp - export entities from plugins back to the HL engine
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "linkent.h" // LINK_ENTITY_TO_PLUGIN
|
||||
|
||||
// Entity lists for plugins
|
||||
LINK_ENTITY_TO_PLUGIN(adminmod_timer, "adminmod");
|
||||
@@ -1,240 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// log_mega.cpp - logging routines
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h> // vsnprintf, etc
|
||||
#include <stdarg.h> // va_start, etc
|
||||
|
||||
#include <extdll.h> // always
|
||||
#include "enginecallbacks.h" // ALERT, etc
|
||||
|
||||
#include "sdk_util.h" // SERVER_PRINT, etc
|
||||
#include "log_meta.h" // me
|
||||
#include "osdep.h" // win32 vsnprintf, etc
|
||||
#include "support_meta.h" // MAX
|
||||
|
||||
cvar_t meta_debug = {"meta_debug", "0", FCVAR_EXTDLL, 0, NULL};
|
||||
|
||||
int meta_debug_value = 0; //meta_debug_value is converted from float(meta_debug.value) to int on every frame
|
||||
|
||||
enum MLOG_SERVICE {
|
||||
mlsCONS = 1,
|
||||
mlsDEV,
|
||||
mlsIWEL,
|
||||
mlsCLIENT
|
||||
};
|
||||
|
||||
static void buffered_ALERT(MLOG_SERVICE service, ALERT_TYPE atype, const char *prefix, const char *fmt, va_list ap);
|
||||
|
||||
// Print to console.
|
||||
void DLLINTERNAL META_CONS(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char buf[MAX_LOGMSG_LEN];
|
||||
unsigned int len;
|
||||
|
||||
va_start(ap, fmt);
|
||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
len=strlen(buf);
|
||||
if(len < sizeof(buf)-2) { // -1 null, -1 for newline
|
||||
buf[len+0] = '\n';
|
||||
buf[len+1] = 0;
|
||||
}
|
||||
else
|
||||
buf[len-1] = '\n';
|
||||
|
||||
SERVER_PRINT(buf);
|
||||
}
|
||||
|
||||
// Log developer-level messages (obsoleted).
|
||||
static const char *const prefixDEV = "[META] dev:";
|
||||
void DLLINTERNAL META_DEV(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
int dev;
|
||||
|
||||
if(NULL != g_engfuncs.pfnCVarGetFloat) {
|
||||
dev=(int) CVAR_GET_FLOAT("developer");
|
||||
if(dev==0) return;
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
buffered_ALERT(mlsDEV, at_logged, prefixDEV, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
// Log infos.
|
||||
static const char *const prefixINFO = "[META] INFO:";
|
||||
void DLLINTERNAL META_INFO(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
buffered_ALERT(mlsIWEL, at_logged, prefixINFO, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
// Log warnings.
|
||||
static const char *const prefixWARNING = "[META] WARNING:";
|
||||
void DLLINTERNAL META_WARNING(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
buffered_ALERT(mlsIWEL, at_logged, prefixWARNING, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
// Log errors.
|
||||
static const char *const prefixERROR = "[META] ERROR:";
|
||||
void DLLINTERNAL META_ERROR(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
buffered_ALERT(mlsIWEL, at_logged, prefixERROR, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
// Normal log messages.
|
||||
static const char *const prefixLOG = "[META]";
|
||||
void DLLINTERNAL META_LOG(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
buffered_ALERT(mlsIWEL, at_logged, prefixLOG, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
// Print to client.
|
||||
void DLLINTERNAL META_CLIENT(edict_t *pEntity, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char buf[MAX_CLIENTMSG_LEN];
|
||||
unsigned int len;
|
||||
|
||||
va_start(ap, fmt);
|
||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
len=strlen(buf);
|
||||
if(len < sizeof(buf)-2) { // -1 null, -1 for newline
|
||||
buf[len+0] = '\n';
|
||||
buf[len+1] = 0;
|
||||
}
|
||||
else
|
||||
buf[len-1] = '\n';
|
||||
|
||||
CLIENT_PRINTF(pEntity, print_console, buf);
|
||||
}
|
||||
|
||||
#ifndef __BUILD_FAST_METAMOD__
|
||||
|
||||
static int debug_level;
|
||||
|
||||
void DLLINTERNAL META_DEBUG_SET_LEVEL(int level) {
|
||||
debug_level = level;
|
||||
}
|
||||
|
||||
void DLLINTERNAL META_DO_DEBUG(const char *fmt, ...) {
|
||||
char meta_debug_str[1024];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
safevoid_vsnprintf(meta_debug_str, sizeof(meta_debug_str), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
ALERT(at_logged, "[META] (debug:%d) %s\n", debug_level, meta_debug_str);
|
||||
}
|
||||
|
||||
#endif /*!__BUILD_FAST_METAMOD__*/
|
||||
|
||||
class BufferedMessage : public class_metamod_new {
|
||||
public:
|
||||
MLOG_SERVICE service;
|
||||
ALERT_TYPE atype;
|
||||
const char *prefix;
|
||||
char buf[MAX_LOGMSG_LEN];
|
||||
BufferedMessage *next;
|
||||
};
|
||||
|
||||
static BufferedMessage *messageQueueStart = NULL;
|
||||
static BufferedMessage *messageQueueEnd = NULL;
|
||||
|
||||
static void buffered_ALERT(MLOG_SERVICE service, ALERT_TYPE atype, const char *prefix, const char *fmt, va_list ap) {
|
||||
char buf[MAX_LOGMSG_LEN];
|
||||
BufferedMessage *msg;
|
||||
|
||||
if (NULL != g_engfuncs.pfnAlertMessage) {
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
ALERT(atype, "%s %s\n", prefix, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
// Engine AlertMessage function not available. Buffer message.
|
||||
msg = new BufferedMessage;
|
||||
if (NULL == msg) {
|
||||
// though luck, gonna lose this message
|
||||
return;
|
||||
}
|
||||
msg->service = service;
|
||||
msg->atype = atype;
|
||||
msg->prefix = prefix;
|
||||
vsnprintf(msg->buf, sizeof(buf), fmt, ap);
|
||||
msg->next = NULL;
|
||||
|
||||
if (NULL == messageQueueEnd) {
|
||||
messageQueueStart = messageQueueEnd = msg;
|
||||
} else {
|
||||
messageQueueEnd->next = msg;
|
||||
messageQueueEnd = msg;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Flushes the message queue, printing messages to the respective
|
||||
// service. This function doesn't check anymore if the g_engfuncs
|
||||
// jumptable is set. Don't call it if it isn't set.
|
||||
void DLLINTERNAL flush_ALERT_buffer(void) {
|
||||
BufferedMessage *msg = messageQueueStart;
|
||||
int dev = (int) CVAR_GET_FLOAT("developer");
|
||||
|
||||
while (NULL != msg) {
|
||||
if(msg->service == mlsDEV && dev==0) {
|
||||
;
|
||||
} else {
|
||||
ALERT(msg->atype, "b>%s %s\n", msg->prefix, msg->buf);
|
||||
}
|
||||
messageQueueStart = messageQueueStart->next;
|
||||
delete msg;
|
||||
msg = messageQueueStart;
|
||||
}
|
||||
|
||||
messageQueueStart = messageQueueEnd = NULL;
|
||||
}
|
||||
@@ -1,724 +0,0 @@
|
||||
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// meta_eiface.cpp - wrapper for engine/dll interface
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include <stdio.h> // fprintf()
|
||||
#include <stdlib.h> // exit()
|
||||
#include <string.h> // memset(), memcpy()
|
||||
|
||||
#include "meta_eiface.h" // me
|
||||
#include "dllapi.h" // FN_CVARVALUE, FN_CVARVALUE2
|
||||
#include "engine_t.h" // Engine
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// meta_new_dll_functions_t
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// static member initialisation
|
||||
int meta_new_dll_functions_t::sm_version DLLHIDDEN = 0;
|
||||
|
||||
|
||||
meta_new_dll_functions_t::meta_new_dll_functions_t(
|
||||
void (*_pfnOnFreeEntPrivateData) (edict_t*),
|
||||
void (*_pfnGameShutdown) (void),
|
||||
int (*_pfnShouldCollide) (edict_t*, edict_t*),
|
||||
void (*_pfnCvarValue) (const edict_t*, const char*),
|
||||
void (*_pfnCvarValue2) (const edict_t*, int, const char*, const char*)
|
||||
)
|
||||
{
|
||||
pfnOnFreeEntPrivateData = _pfnOnFreeEntPrivateData;
|
||||
pfnGameShutdown = _pfnGameShutdown;
|
||||
pfnShouldCollide = _pfnShouldCollide;
|
||||
pfnCvarValue = _pfnCvarValue;
|
||||
pfnCvarValue2 = _pfnCvarValue2;
|
||||
|
||||
memset( dummies, 0, sizeof(pdummyfunc) * c_NumDummies );
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DLLINTERNAL meta_new_dll_functions_t::copy_to( NEW_DLL_FUNCTIONS *_pFuncs )
|
||||
{
|
||||
// This is where the magic happens. We check what version of the
|
||||
// NEW_DLL_FUNCTIONS interface the engine has and calculate the size of
|
||||
// that interface. Then we only copy the function pointers present in
|
||||
// that version over to the receiver, so that we do not overwrite his
|
||||
// memory with functions that he doesn't know of in his copy of the
|
||||
// struct.
|
||||
size_t size = get_size();
|
||||
|
||||
if ( 0 == size ) {
|
||||
// Ok, this is a real problem and should *not* happen.
|
||||
// We try to work with NEW_DLL_FUNCTIONS without knowing what
|
||||
// interface the attached engine uses. This means that the classes
|
||||
// defined herein are not used in the way they are meant to because
|
||||
// someone forgot to first create a HL_enginefuncs_t object and
|
||||
// initialise it with the pointers passed from the engine.
|
||||
// We treat this as a major developer error and bluntly exit the
|
||||
// whole process, assuming that this will never happen on a
|
||||
// production server as it should have been caught by the developer
|
||||
// during testing.
|
||||
//
|
||||
// We use a printf() to complain since we do not know if we have
|
||||
// already attached to the engine and can use its alerting
|
||||
// functions. This should be augemnted with a windows version
|
||||
// popping open a message box.
|
||||
fprintf( stderr, "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" );
|
||||
fprintf( stderr, "ERROR: INTERNAL ERROR.\n" );
|
||||
fprintf( stderr, " Attempt to use meta_new_dll_functions_t without initialised engine interface version!\n" );
|
||||
fprintf( stderr, " %s at %d\n", __FILE__, __LINE__ );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memcpy( _pFuncs, this, size );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int DLLINTERNAL meta_new_dll_functions_t::determine_interface_version( void )
|
||||
{
|
||||
// If the meta_enginefuncs_t::version is 0, i.e. has not yet been
|
||||
// determined, that is a problem and an error. We should probably throw
|
||||
// a fit here or something.
|
||||
// For now we just return 0 and leave it to the caller to complain.
|
||||
if (meta_enginefuncs_t::version() == 0) return 0;
|
||||
|
||||
// The default version is 1.
|
||||
sm_version = 1;
|
||||
|
||||
// With the enginefuncs interface version 156 the function
|
||||
// pfnCvarValue() was added, which we call version 2.
|
||||
if (meta_enginefuncs_t::version() >= 156) sm_version = 2;
|
||||
|
||||
// With the enginefuncs interface version 157 the function
|
||||
// pfnCvarValue2() was added, which we call version 3.
|
||||
if (meta_enginefuncs_t::version() >= 157) sm_version = 3;
|
||||
|
||||
return sm_version;
|
||||
}
|
||||
|
||||
|
||||
size_t DLLINTERNAL meta_new_dll_functions_t::get_size( int _version )
|
||||
{
|
||||
size_t size = sizeof(NEW_DLL_FUNCTIONS);
|
||||
|
||||
if ( 0 == _version ) {
|
||||
// Use the current engine's interface version
|
||||
_version = version();
|
||||
|
||||
// Error: meta_enginefuncs_t::version probably not yet set up.
|
||||
if ( 0 == _version ) return 0;
|
||||
}
|
||||
|
||||
switch( _version ) {
|
||||
case 1:
|
||||
// Version 1 is missing all functions from CvarValue() on.
|
||||
size -= sizeof(FN_CVARVALUE);
|
||||
case 2:
|
||||
// Version 2 is missing all functions from CvarValue2() on.
|
||||
size -= sizeof(FN_CVARVALUE2);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// meta_enginefuncs_t
|
||||
// --------------------------------------------------------------
|
||||
|
||||
// static member initialisation
|
||||
int meta_enginefuncs_t::sm_version = 0;
|
||||
|
||||
|
||||
|
||||
meta_enginefuncs_t::meta_enginefuncs_t(
|
||||
int (*_pfnPrecacheModel) (char*),
|
||||
int (*_pfnPrecacheSound) (char*),
|
||||
void (*_pfnSetModel) (edict_t*, const char*),
|
||||
int (*_pfnModelIndex) (const char*),
|
||||
int (*_pfnModelFrames) (int),
|
||||
void (*_pfnSetSize) (edict_t*, const float*, const float*),
|
||||
void (*_pfnChangeLevel) (char*, char*),
|
||||
void (*_pfnGetSpawnParms) (edict_t*),
|
||||
void (*_pfnSaveSpawnParms) (edict_t*),
|
||||
float (*_pfnVecToYaw) (const float*),
|
||||
void (*_pfnVecToAngles) (const float*, float*),
|
||||
void (*_pfnMoveToOrigin) (edict_t*, const float*, float, int),
|
||||
void (*_pfnChangeYaw) (edict_t*),
|
||||
void (*_pfnChangePitch) (edict_t*),
|
||||
edict_t* (*_pfnFindEntityByString) (edict_t*, const char*, const char*),
|
||||
int (*_pfnGetEntityIllum) (edict_t*),
|
||||
edict_t* (*_pfnFindEntityInSphere) (edict_t*, const float*, float),
|
||||
edict_t* (*_pfnFindClientInPVS) (edict_t*),
|
||||
edict_t* (*_pfnEntitiesInPVS) (edict_t*),
|
||||
void (*_pfnMakeVectors) (const float*),
|
||||
void (*_pfnAngleVectors) (const float*, float*, float*, float*),
|
||||
edict_t* (*_pfnCreateEntity) (void),
|
||||
void (*_pfnRemoveEntity) (edict_t*),
|
||||
edict_t* (*_pfnCreateNamedEntity) (int),
|
||||
void (*_pfnMakeStatic) (edict_t*),
|
||||
int (*_pfnEntIsOnFloor) (edict_t*),
|
||||
int (*_pfnDropToFloor) (edict_t*),
|
||||
int (*_pfnWalkMove) (edict_t*, float, float, int),
|
||||
void (*_pfnSetOrigin) (edict_t*, const float*),
|
||||
void (*_pfnEmitSound) (edict_t*, int, const char*, float, float, int, int),
|
||||
void (*_pfnEmitAmbientSound) (edict_t*, float*, const char*, float, float, int, int),
|
||||
void (*_pfnTraceLine) (const float*, const float*, int, edict_t*, TraceResult*),
|
||||
void (*_pfnTraceToss) (edict_t*, edict_t*, TraceResult*),
|
||||
int (*_pfnTraceMonsterHull) (edict_t*, const float*, const float*, int, edict_t*, TraceResult*),
|
||||
void (*_pfnTraceHull) (const float*, const float*, int, int, edict_t*, TraceResult*),
|
||||
void (*_pfnTraceModel) (const float*, const float*, int, edict_t*, TraceResult*),
|
||||
const char* (*_pfnTraceTexture) (edict_t*, const float*, const float*),
|
||||
void (*_pfnTraceSphere) (const float*, const float*, int, float, edict_t*, TraceResult*),
|
||||
void (*_pfnGetAimVector) (edict_t*, float, float*),
|
||||
void (*_pfnServerCommand) (char*),
|
||||
void (*_pfnServerExecute) (void),
|
||||
void (*_pfnClientCommand) (edict_t*, char*, ...),
|
||||
void (*_pfnParticleEffect) (const float*, const float*, float, float),
|
||||
void (*_pfnLightStyle) (int, char*),
|
||||
int (*_pfnDecalIndex) (const char*),
|
||||
int (*_pfnPointContents) (const float*),
|
||||
void (*_pfnMessageBegin) (int, int, const float*, edict_t*),
|
||||
void (*_pfnMessageEnd) (void),
|
||||
void (*_pfnWriteByte) (int),
|
||||
void (*_pfnWriteChar) (int),
|
||||
void (*_pfnWriteShort) (int),
|
||||
void (*_pfnWriteLong) (int),
|
||||
void (*_pfnWriteAngle) (float),
|
||||
void (*_pfnWriteCoord) (float),
|
||||
void (*_pfnWriteString) (const char*),
|
||||
void (*_pfnWriteEntity) (int),
|
||||
void (*_pfnCVarRegister) (cvar_t*),
|
||||
float (*_pfnCVarGetFloat) (const char*),
|
||||
const char* (*_pfnCVarGetString) (const char*),
|
||||
void (*_pfnCVarSetFloat) (const char*, float),
|
||||
void (*_pfnCVarSetString) (const char*, const char*),
|
||||
void (*_pfnAlertMessage) (ALERT_TYPE, char*, ...),
|
||||
void (*_pfnEngineFprintf) (void*, char*, ...),
|
||||
void* (*_pfnPvAllocEntPrivateData) (edict_t*, int32),
|
||||
void* (*_pfnPvEntPrivateData) (edict_t*),
|
||||
void (*_pfnFreeEntPrivateData) (edict_t*),
|
||||
const char* (*_pfnSzFromIndex) (int),
|
||||
int (*_pfnAllocString) (const char*),
|
||||
struct entvars_s*(*_pfnGetVarsOfEnt) (edict_t*),
|
||||
edict_t* (*_pfnPEntityOfEntOffset) (int),
|
||||
int (*_pfnEntOffsetOfPEntity) (const edict_t*),
|
||||
int (*_pfnIndexOfEdict) (const edict_t*),
|
||||
edict_t* (*_pfnPEntityOfEntIndex) (int),
|
||||
edict_t* (*_pfnFindEntityByVars) (struct entvars_s*),
|
||||
void* (*_pfnGetModelPtr) (edict_t*),
|
||||
int (*_pfnRegUserMsg) (const char*, int),
|
||||
void (*_pfnAnimationAutomove) (const edict_t*, float),
|
||||
void (*_pfnGetBonePosition) (const edict_t*, int, float*, float* ),
|
||||
uint32 (*_pfnFunctionFromName) (const char*),
|
||||
const char* (*_pfnNameForFunction) (uint32),
|
||||
void (*_pfnClientPrintf) (edict_t*, PRINT_TYPE, const char*),
|
||||
void (*_pfnServerPrint) (const char*),
|
||||
const char* (*_pfnCmd_Args) (void),
|
||||
const char* (*_pfnCmd_Argv) (int argc),
|
||||
int (*_pfnCmd_Argc) (void),
|
||||
void (*_pfnGetAttachment) (const edict_t*, int, float*, float*),
|
||||
void (*_pfnCRC32_Init) (CRC32_t*),
|
||||
void (*_pfnCRC32_ProcessBuffer) (CRC32_t*, void*, int),
|
||||
void (*_pfnCRC32_ProcessByte) (CRC32_t*, unsigned char),
|
||||
CRC32_t (*_pfnCRC32_Final) (CRC32_t),
|
||||
int32 (*_pfnRandomLong) (int32, int32),
|
||||
float (*_pfnRandomFloat) (float, float),
|
||||
void (*_pfnSetView) (const edict_t*, const edict_t*),
|
||||
float (*_pfnTime) (void),
|
||||
void (*_pfnCrosshairAngle) (const edict_t*, float, float),
|
||||
byte* (*_pfnLoadFileForMe) (char*, int*),
|
||||
void (*_pfnFreeFile) (void*),
|
||||
void (*_pfnEndSection) (const char*),
|
||||
int (*_pfnCompareFileTime) (char*, char*, int*),
|
||||
void (*_pfnGetGameDir) (char*),
|
||||
void (*_pfnCvar_RegisterVariable) (cvar_t*),
|
||||
void (*_pfnFadeClientVolume) (const edict_t*, int, int, int, int),
|
||||
void (*_pfnSetClientMaxspeed) (const edict_t*, float),
|
||||
edict_t* (*_pfnCreateFakeClient) (const char*),
|
||||
void (*_pfnRunPlayerMove) (edict_t*, const float*, float, float, float, unsigned short, byte, byte),
|
||||
int (*_pfnNumberOfEntities) (void),
|
||||
char* (*_pfnGetInfoKeyBuffer) (edict_t*),
|
||||
char* (*_pfnInfoKeyValue) (char*, char*),
|
||||
void (*_pfnSetKeyValue) (char*, char*, char*),
|
||||
void (*_pfnSetClientKeyValue) (int, char*, char*, char*),
|
||||
int (*_pfnIsMapValid) (char*),
|
||||
void (*_pfnStaticDecal) (const float*, int, int, int),
|
||||
int (*_pfnPrecacheGeneric) (char*),
|
||||
int (*_pfnGetPlayerUserId) (edict_t*),
|
||||
void (*_pfnBuildSoundMsg) (edict_t*, int, const char*, float, float, int, int, int, int, const float*, edict_t*),
|
||||
int (*_pfnIsDedicatedServer) (void),
|
||||
cvar_t* (*_pfnCVarGetPointer) (const char*),
|
||||
unsigned int (*_pfnGetPlayerWONId) (edict_t*),
|
||||
void (*_pfnInfo_RemoveKey) (char*, const char*),
|
||||
const char* (*_pfnGetPhysicsKeyValue) (const edict_t*, const char*),
|
||||
void (*_pfnSetPhysicsKeyValue) (const edict_t*, const char*, const char*),
|
||||
const char* (*_pfnGetPhysicsInfoString) (const edict_t*),
|
||||
unsigned short (*_pfnPrecacheEvent) (int, const char*),
|
||||
void (*_pfnPlaybackEvent) (int, const edict_t*, unsigned short, float, float*, float*, float, float, int, int, int, int),
|
||||
unsigned char* (*_pfnSetFatPVS) (float*),
|
||||
unsigned char* (*_pfnSetFatPAS) (float*),
|
||||
int (*_pfnCheckVisibility) (const edict_t*, unsigned char*),
|
||||
void (*_pfnDeltaSetField) (struct delta_s*, const char*),
|
||||
void (*_pfnDeltaUnsetField) (struct delta_s*, const char*),
|
||||
void (*_pfnDeltaAddEncoder) (char*, void (*)(struct delta_s*, const unsigned char*, const unsigned char*)),
|
||||
int (*_pfnGetCurrentPlayer) (void),
|
||||
int (*_pfnCanSkipPlayer) (const edict_t*),
|
||||
int (*_pfnDeltaFindField) (struct delta_s*, const char*),
|
||||
void (*_pfnDeltaSetFieldByIndex) (struct delta_s*, int),
|
||||
void (*_pfnDeltaUnsetFieldByIndex) (struct delta_s*, int),
|
||||
void (*_pfnSetGroupMask) (int, int),
|
||||
int (*_pfnCreateInstancedBaseline) (int, struct entity_state_s*),
|
||||
void (*_pfnCvar_DirectSet) (struct cvar_s*, char*),
|
||||
void (*_pfnForceUnmodified) (FORCE_TYPE, float*, float*, const char*),
|
||||
void (*_pfnGetPlayerStats) (const edict_t*, int*, int*),
|
||||
void (*_pfnAddServerCommand) (char*, void (*) (void)),
|
||||
qboolean (*_pfnVoice_GetClientListening) (int, int),
|
||||
qboolean (*_pfnVoice_SetClientListening) (int, int, qboolean),
|
||||
const char* (*_pfnGetPlayerAuthId) (edict_t*),
|
||||
sequenceEntry_s* (*_pfnSequenceGet) (const char*, const char*),
|
||||
sentenceEntry_s* (*_pfnSequencePickSentence) (const char*, int, int*),
|
||||
int (*_pfnGetFileSize) (char*),
|
||||
unsigned int (*_pfnGetApproxWavePlayLen) (const char*),
|
||||
int (*_pfnIsCareerMatch) (void),
|
||||
int (*_pfnGetLocalizedStringLength) (const char*),
|
||||
void (*_pfnRegisterTutorMessageShown) (int),
|
||||
int (*_pfnGetTimesTutorMessageShown) (int),
|
||||
void (*_pfnProcessTutorMessageDecayBuffer) (int*, int),
|
||||
void (*_pfnConstructTutorMessageDecayBuffer)(int*, int),
|
||||
void (*_pfnResetTutorMessageDecayData) (void),
|
||||
void (*_pfnQueryClientCvarValue) (const edict_t*, const char*),
|
||||
void (*_pfnQueryClientCvarValue2) (const edict_t*, const char*, int),
|
||||
int (*_pfnEngCheckParm) (const char*, char**)
|
||||
)
|
||||
{
|
||||
pfnPrecacheModel = _pfnPrecacheModel;
|
||||
pfnPrecacheSound = _pfnPrecacheSound;
|
||||
pfnSetModel = _pfnSetModel;
|
||||
pfnModelIndex = _pfnModelIndex;
|
||||
pfnModelFrames = _pfnModelFrames;
|
||||
pfnSetSize = _pfnSetSize;
|
||||
pfnChangeLevel = _pfnChangeLevel;
|
||||
pfnGetSpawnParms = _pfnGetSpawnParms;
|
||||
pfnSaveSpawnParms = _pfnSaveSpawnParms;
|
||||
pfnVecToYaw = _pfnVecToYaw;
|
||||
pfnVecToAngles = _pfnVecToAngles;
|
||||
pfnMoveToOrigin = _pfnMoveToOrigin;
|
||||
pfnChangeYaw = _pfnChangeYaw;
|
||||
pfnChangePitch = _pfnChangePitch;
|
||||
pfnFindEntityByString = _pfnFindEntityByString;
|
||||
pfnGetEntityIllum = _pfnGetEntityIllum;
|
||||
pfnFindEntityInSphere = _pfnFindEntityInSphere;
|
||||
pfnFindClientInPVS = _pfnFindClientInPVS;
|
||||
pfnEntitiesInPVS = _pfnEntitiesInPVS;
|
||||
pfnMakeVectors = _pfnMakeVectors;
|
||||
pfnAngleVectors = _pfnAngleVectors;
|
||||
pfnCreateEntity = _pfnCreateEntity;
|
||||
pfnRemoveEntity = _pfnRemoveEntity;
|
||||
pfnCreateNamedEntity = _pfnCreateNamedEntity;
|
||||
pfnMakeStatic = _pfnMakeStatic;
|
||||
pfnEntIsOnFloor = _pfnEntIsOnFloor;
|
||||
pfnDropToFloor = _pfnDropToFloor;
|
||||
pfnWalkMove = _pfnWalkMove;
|
||||
pfnSetOrigin = _pfnSetOrigin;
|
||||
pfnEmitSound = _pfnEmitSound;
|
||||
pfnEmitAmbientSound = _pfnEmitAmbientSound;
|
||||
pfnTraceLine = _pfnTraceLine;
|
||||
pfnTraceToss = _pfnTraceToss;
|
||||
pfnTraceMonsterHull = _pfnTraceMonsterHull;
|
||||
pfnTraceHull = _pfnTraceHull;
|
||||
pfnTraceModel = _pfnTraceModel;
|
||||
pfnTraceTexture = _pfnTraceTexture;
|
||||
pfnTraceSphere = _pfnTraceSphere;
|
||||
pfnGetAimVector = _pfnGetAimVector;
|
||||
pfnServerCommand = _pfnServerCommand;
|
||||
pfnServerExecute = _pfnServerExecute;
|
||||
pfnClientCommand = _pfnClientCommand;
|
||||
pfnParticleEffect = _pfnParticleEffect;
|
||||
pfnLightStyle = _pfnLightStyle;
|
||||
pfnDecalIndex = _pfnDecalIndex;
|
||||
pfnPointContents = _pfnPointContents;
|
||||
pfnMessageBegin = _pfnMessageBegin;
|
||||
pfnMessageEnd = _pfnMessageEnd;
|
||||
pfnWriteByte = _pfnWriteByte;
|
||||
pfnWriteChar = _pfnWriteChar;
|
||||
pfnWriteShort = _pfnWriteShort;
|
||||
pfnWriteLong = _pfnWriteLong;
|
||||
pfnWriteAngle = _pfnWriteAngle;
|
||||
pfnWriteCoord = _pfnWriteCoord;
|
||||
pfnWriteString = _pfnWriteString;
|
||||
pfnWriteEntity = _pfnWriteEntity;
|
||||
pfnCVarRegister = _pfnCVarRegister;
|
||||
pfnCVarGetFloat = _pfnCVarGetFloat;
|
||||
pfnCVarGetString = _pfnCVarGetString;
|
||||
pfnCVarSetFloat = _pfnCVarSetFloat;
|
||||
pfnCVarSetString = _pfnCVarSetString;
|
||||
pfnAlertMessage = _pfnAlertMessage;
|
||||
pfnEngineFprintf = _pfnEngineFprintf;
|
||||
pfnPvAllocEntPrivateData = _pfnPvAllocEntPrivateData;
|
||||
pfnPvEntPrivateData = _pfnPvEntPrivateData;
|
||||
pfnFreeEntPrivateData = _pfnFreeEntPrivateData;
|
||||
pfnSzFromIndex = _pfnSzFromIndex;
|
||||
pfnAllocString = _pfnAllocString;
|
||||
pfnGetVarsOfEnt = _pfnGetVarsOfEnt;
|
||||
pfnPEntityOfEntOffset = _pfnPEntityOfEntOffset;
|
||||
pfnEntOffsetOfPEntity = _pfnEntOffsetOfPEntity;
|
||||
pfnIndexOfEdict = _pfnIndexOfEdict;
|
||||
pfnPEntityOfEntIndex = _pfnPEntityOfEntIndex;
|
||||
pfnFindEntityByVars = _pfnFindEntityByVars;
|
||||
pfnGetModelPtr = _pfnGetModelPtr;
|
||||
pfnRegUserMsg = _pfnRegUserMsg;
|
||||
pfnAnimationAutomove = _pfnAnimationAutomove;
|
||||
pfnGetBonePosition = _pfnGetBonePosition;
|
||||
pfnFunctionFromName = _pfnFunctionFromName;
|
||||
pfnNameForFunction = _pfnNameForFunction;
|
||||
pfnClientPrintf = _pfnClientPrintf;
|
||||
pfnServerPrint = _pfnServerPrint;
|
||||
pfnCmd_Args = _pfnCmd_Args;
|
||||
pfnCmd_Argv = _pfnCmd_Argv;
|
||||
pfnCmd_Argc = _pfnCmd_Argc;
|
||||
pfnGetAttachment = _pfnGetAttachment;
|
||||
pfnCRC32_Init = _pfnCRC32_Init;
|
||||
pfnCRC32_ProcessBuffer = _pfnCRC32_ProcessBuffer;
|
||||
pfnCRC32_ProcessByte = _pfnCRC32_ProcessByte;
|
||||
pfnCRC32_Final = _pfnCRC32_Final;
|
||||
pfnRandomLong = _pfnRandomLong;
|
||||
pfnRandomFloat = _pfnRandomFloat;
|
||||
pfnSetView = _pfnSetView;
|
||||
pfnTime = _pfnTime;
|
||||
pfnCrosshairAngle = _pfnCrosshairAngle;
|
||||
pfnLoadFileForMe = _pfnLoadFileForMe;
|
||||
pfnFreeFile = _pfnFreeFile;
|
||||
pfnEndSection = _pfnEndSection;
|
||||
pfnCompareFileTime = _pfnCompareFileTime;
|
||||
pfnGetGameDir = _pfnGetGameDir;
|
||||
pfnCvar_RegisterVariable = _pfnCvar_RegisterVariable;
|
||||
pfnFadeClientVolume = _pfnFadeClientVolume;
|
||||
pfnSetClientMaxspeed = _pfnSetClientMaxspeed;
|
||||
pfnCreateFakeClient = _pfnCreateFakeClient;
|
||||
pfnRunPlayerMove = _pfnRunPlayerMove;
|
||||
pfnNumberOfEntities = _pfnNumberOfEntities;
|
||||
pfnGetInfoKeyBuffer = _pfnGetInfoKeyBuffer;
|
||||
pfnInfoKeyValue = _pfnInfoKeyValue;
|
||||
pfnSetKeyValue = _pfnSetKeyValue;
|
||||
pfnSetClientKeyValue = _pfnSetClientKeyValue;
|
||||
pfnIsMapValid = _pfnIsMapValid;
|
||||
pfnStaticDecal = _pfnStaticDecal;
|
||||
pfnPrecacheGeneric = _pfnPrecacheGeneric;
|
||||
pfnGetPlayerUserId = _pfnGetPlayerUserId;
|
||||
pfnBuildSoundMsg = _pfnBuildSoundMsg;
|
||||
pfnIsDedicatedServer = _pfnIsDedicatedServer;
|
||||
pfnCVarGetPointer = _pfnCVarGetPointer;
|
||||
pfnGetPlayerWONId = _pfnGetPlayerWONId;
|
||||
pfnInfo_RemoveKey = _pfnInfo_RemoveKey;
|
||||
pfnGetPhysicsKeyValue = _pfnGetPhysicsKeyValue;
|
||||
pfnSetPhysicsKeyValue = _pfnSetPhysicsKeyValue;
|
||||
pfnGetPhysicsInfoString = _pfnGetPhysicsInfoString;
|
||||
pfnPrecacheEvent = _pfnPrecacheEvent;
|
||||
pfnPlaybackEvent = _pfnPlaybackEvent;
|
||||
pfnSetFatPVS = _pfnSetFatPVS;
|
||||
pfnSetFatPAS = _pfnSetFatPAS;
|
||||
pfnCheckVisibility = _pfnCheckVisibility;
|
||||
pfnDeltaSetField = _pfnDeltaSetField;
|
||||
pfnDeltaUnsetField = _pfnDeltaUnsetField;
|
||||
pfnDeltaAddEncoder = _pfnDeltaAddEncoder;
|
||||
pfnGetCurrentPlayer = _pfnGetCurrentPlayer;
|
||||
pfnCanSkipPlayer = _pfnCanSkipPlayer;
|
||||
pfnDeltaFindField = _pfnDeltaFindField;
|
||||
pfnDeltaSetFieldByIndex = _pfnDeltaSetFieldByIndex;
|
||||
pfnDeltaUnsetFieldByIndex = _pfnDeltaUnsetFieldByIndex;
|
||||
pfnSetGroupMask = _pfnSetGroupMask;
|
||||
pfnCreateInstancedBaseline = _pfnCreateInstancedBaseline;
|
||||
pfnCvar_DirectSet = _pfnCvar_DirectSet;
|
||||
pfnForceUnmodified = _pfnForceUnmodified;
|
||||
pfnGetPlayerStats = _pfnGetPlayerStats;
|
||||
pfnAddServerCommand = _pfnAddServerCommand;
|
||||
pfnVoice_GetClientListening = _pfnVoice_GetClientListening;
|
||||
pfnVoice_SetClientListening = _pfnVoice_SetClientListening;
|
||||
pfnGetPlayerAuthId = _pfnGetPlayerAuthId;
|
||||
pfnSequenceGet = _pfnSequenceGet;
|
||||
pfnSequencePickSentence = _pfnSequencePickSentence;
|
||||
pfnGetFileSize = _pfnGetFileSize;
|
||||
pfnGetApproxWavePlayLen = _pfnGetApproxWavePlayLen;
|
||||
pfnIsCareerMatch = _pfnIsCareerMatch;
|
||||
pfnGetLocalizedStringLength = _pfnGetLocalizedStringLength;
|
||||
pfnRegisterTutorMessageShown = _pfnRegisterTutorMessageShown;
|
||||
pfnGetTimesTutorMessageShown = _pfnGetTimesTutorMessageShown;
|
||||
pfnProcessTutorMessageDecayBuffer = _pfnProcessTutorMessageDecayBuffer;
|
||||
pfnConstructTutorMessageDecayBuffer = _pfnConstructTutorMessageDecayBuffer;
|
||||
pfnResetTutorMessageDecayData = _pfnResetTutorMessageDecayData;
|
||||
pfnQueryClientCvarValue = _pfnQueryClientCvarValue;
|
||||
pfnQueryClientCvarValue2 = _pfnQueryClientCvarValue2;
|
||||
pfnEngCheckParm = _pfnEngCheckParm;
|
||||
|
||||
memset( extra_functions, 0, sizeof(extra_functions));
|
||||
|
||||
memset( dummies, 0, sizeof(pdummyfunc) * c_NumDummies );
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// HL_enginefuncs
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
void HL_enginefuncs_t::initialise_interface( enginefuncs_t *_pFuncs )
|
||||
{
|
||||
set_from( _pFuncs );
|
||||
|
||||
// Now the pfnAlertMessage is available and we trust it to be a valid
|
||||
// pointer, so flush the message buffer.
|
||||
flush_ALERT_buffer();
|
||||
|
||||
determine_engine_interface_version();
|
||||
fixup_engine_interface();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// The following part (i.e. the end) of the enginefuncs_t struct is
|
||||
// used to determine the engine interface version since it is the one
|
||||
// that changed since SDK 212 engines. We call this the "signature" of
|
||||
// the enginefuncs interface.
|
||||
//
|
||||
// Default version is 138. That's what the SDK says.
|
||||
//
|
||||
// 144: const char *(*pfnGetPlayerAuthId) ( edict_t *e );
|
||||
//
|
||||
// // PSV: Added for CZ training map
|
||||
// // const char *(*pfnKeyNameForBinding) ( const char* pBinding );
|
||||
//
|
||||
// sequenceEntry_s* (*pfnSequenceGet) ( const char* fileName, const char* entryName );
|
||||
// sentenceEntry_s* (*pfnSequencePickSentence) ( const char* groupName, int pickMethod, int *picked );
|
||||
//
|
||||
// // LH: Give access to filesize via filesystem
|
||||
// 147: int (*pfnGetFileSize) ( char *filename );
|
||||
//
|
||||
// unsigned int (*pfnGetApproxWavePlayLen) (const char *filepath);
|
||||
// // MDC: Added for CZ career-mode
|
||||
// int (*pfnIsCareerMatch) ( void );
|
||||
//
|
||||
// // BGC: return the number of characters of the localized string referenced by using "label"
|
||||
// int (*pfnGetLocalizedStringLength) (const char *label);
|
||||
//
|
||||
// // BGC: added to facilitate persistent storage of tutor message decay values for
|
||||
// // different career game profiles. Also needs to persist regardless of mp.dll being
|
||||
// // destroyed and recreated.
|
||||
// void (*pfnRegisterTutorMessageShown) (int mid);
|
||||
// int (*pfnGetTimesTutorMessageShown) (int mid);
|
||||
// void (*pfnProcessTutorMessageDecayBuffer) (int *buffer, int bufferLength);
|
||||
// void (*pfnConstructTutorMessageDecayBuffer) (int *buffer, int bufferLength);
|
||||
// 155: void (*pfnResetTutorMessageDecayData) ( void );
|
||||
|
||||
// 156: void (*pfnQueryClientCvarValue) ( const edict_t *player, const char *cvarName );
|
||||
// 157: void (*pfnQueryClientCvarValue2) ( const edict_t *player, const char *cvarName, int requestID );
|
||||
// 158: int (*pfnEngCheckParm) ( const char *pchCmdLineToke, char **pchNextValue );
|
||||
|
||||
void HL_enginefuncs_t::determine_engine_interface_version( void )
|
||||
{
|
||||
// We only need to do this once.
|
||||
if (0 != sm_version) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Test every pointer that is part of the signature if it is a valid
|
||||
// pointer. If it is not, we set it explicitly to NULL.
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnGetPlayerAuthId) ) {
|
||||
pfnGetPlayerAuthId = NULL;
|
||||
}
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnSequenceGet) ) {
|
||||
pfnSequenceGet = NULL;
|
||||
}
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnSequencePickSentence) ) {
|
||||
pfnSequencePickSentence = NULL;
|
||||
}
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnGetFileSize) ) {
|
||||
pfnGetFileSize = NULL;
|
||||
}
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnGetApproxWavePlayLen) ) {
|
||||
pfnGetApproxWavePlayLen = NULL;
|
||||
}
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnIsCareerMatch) ) {
|
||||
pfnIsCareerMatch = NULL;
|
||||
}
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnGetLocalizedStringLength) ) {
|
||||
pfnGetLocalizedStringLength = NULL;
|
||||
}
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnRegisterTutorMessageShown) ) {
|
||||
pfnRegisterTutorMessageShown = NULL;
|
||||
}
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnGetTimesTutorMessageShown) ) {
|
||||
pfnGetTimesTutorMessageShown = NULL;
|
||||
}
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnProcessTutorMessageDecayBuffer) ) {
|
||||
pfnProcessTutorMessageDecayBuffer = NULL;
|
||||
}
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnConstructTutorMessageDecayBuffer) ) {
|
||||
pfnConstructTutorMessageDecayBuffer = NULL;
|
||||
}
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnResetTutorMessageDecayData) ) {
|
||||
pfnResetTutorMessageDecayData = NULL;
|
||||
}
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnQueryClientCvarValue) ) {
|
||||
pfnQueryClientCvarValue = NULL;
|
||||
}
|
||||
if ( ! Engine.info.is_valid_code_pointer(pfnQueryClientCvarValue2) ) {
|
||||
pfnQueryClientCvarValue2 = NULL;
|
||||
}
|
||||
|
||||
// Now begins our heuristic, where we try to determine the engine
|
||||
// interface version.
|
||||
// As alluded to above we are currently only interested, and thus
|
||||
// only detect, versions 144, 147, 156 or 157 (defined by us).
|
||||
|
||||
// The minimal default is 138.
|
||||
sm_version = 138;
|
||||
|
||||
// If GetPlayerAuthId() is present, it is at least 144,
|
||||
// otherwise leave it at the default 138.
|
||||
// This may give incorrect results for *really* old engine versions,
|
||||
// i.e. pre 1.1.0.8. We live with that risk. No one uses them anymore.
|
||||
// Really.
|
||||
if ( pfnGetPlayerAuthId == NULL ) {
|
||||
return;
|
||||
}
|
||||
sm_version = 144;
|
||||
|
||||
// The two function pointers for pfnSequenceGet() and
|
||||
// pfnSequencePickSentence() are only valid in a few engine versions
|
||||
// and are set to NULL in most other version, so they don't get
|
||||
// checked.
|
||||
|
||||
// If pfnGetFileSize() is present, it is at least 147,
|
||||
// otherwise leave it at the so far determined value.
|
||||
if ( pfnGetFileSize == NULL ) {
|
||||
return;
|
||||
}
|
||||
sm_version = 147;
|
||||
|
||||
// Now it gets a bit fuzzy. If all of the functions following GetFileSize()
|
||||
// but before QueryClientCvarValue() are valid, it is at least 155.
|
||||
// If even one of them is NULL, then our version can't be higher than 147,
|
||||
// so use 147. Actually, it could be that there exist engine
|
||||
// versions where one of them is NULL but the interface is still at
|
||||
// least 155. If such an engine is found in use, adaptions need to be
|
||||
// made.
|
||||
// (Yes, I know this could be done with a little hacky for() loop. We
|
||||
// don't need to do hacky here.)
|
||||
int cntInvals = 0;
|
||||
if ( pfnGetApproxWavePlayLen == NULL ) cntInvals++;
|
||||
if ( pfnIsCareerMatch == NULL ) cntInvals++;
|
||||
if ( pfnGetLocalizedStringLength == NULL ) cntInvals++;
|
||||
if ( pfnRegisterTutorMessageShown == NULL ) cntInvals++;
|
||||
if ( pfnGetTimesTutorMessageShown == NULL ) cntInvals++;
|
||||
if ( pfnProcessTutorMessageDecayBuffer == NULL ) cntInvals++;
|
||||
if ( pfnConstructTutorMessageDecayBuffer == NULL ) cntInvals++;
|
||||
if ( pfnResetTutorMessageDecayData == NULL ) cntInvals++;
|
||||
|
||||
if ( cntInvals > 0 ) {
|
||||
return;
|
||||
}
|
||||
sm_version = 155;
|
||||
|
||||
// All functions up to QueryClientCvarValue() are valid.
|
||||
// If QueryClientCvarValue() is not valid, leave it at the so far
|
||||
// determined version. Otherwise the version is at least 156.
|
||||
if ( pfnQueryClientCvarValue == NULL) {
|
||||
return;
|
||||
}
|
||||
sm_version = 156;
|
||||
|
||||
// All functions up to QueryClientCvarValue2() are valid.
|
||||
// If QueryClientCvarValue2() is not valid, leave it at the so far
|
||||
// determined version. Otherwise the version is at least 157.
|
||||
if ( pfnQueryClientCvarValue2 == NULL) {
|
||||
return;
|
||||
}
|
||||
sm_version = 157;
|
||||
|
||||
// All functions up to EngCheckParm() are valid.
|
||||
// If EngCheckParm() is not valid, leave it at the so far determined
|
||||
// version. Otherwise the version is at least 158.
|
||||
if ( pfnEngCheckParm == NULL) {
|
||||
return;
|
||||
}
|
||||
sm_version = 158;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void HL_enginefuncs_t::fixup_engine_interface( void )
|
||||
{
|
||||
// This function will make sure that all function pointers that aren't
|
||||
// valid are set to NULL, depending on the engine interface version.
|
||||
// Sometimes a pointer has a valid value although the function doesn't
|
||||
// exist in the interface version.
|
||||
|
||||
switch ( version() ) {
|
||||
case 138:
|
||||
pfnGetPlayerAuthId = NULL;
|
||||
case 144:
|
||||
pfnSequenceGet = NULL;
|
||||
pfnSequencePickSentence = NULL;
|
||||
pfnGetFileSize = NULL;
|
||||
case 147:
|
||||
pfnGetApproxWavePlayLen = NULL;
|
||||
pfnIsCareerMatch = NULL;
|
||||
pfnGetLocalizedStringLength = NULL;
|
||||
pfnRegisterTutorMessageShown = NULL;
|
||||
pfnGetTimesTutorMessageShown = NULL;
|
||||
pfnProcessTutorMessageDecayBuffer = NULL;
|
||||
pfnConstructTutorMessageDecayBuffer = NULL;
|
||||
pfnResetTutorMessageDecayData = NULL;
|
||||
case 155:
|
||||
pfnQueryClientCvarValue = NULL;
|
||||
case 156:
|
||||
pfnQueryClientCvarValue2 = NULL;
|
||||
case 157:
|
||||
pfnEngCheckParm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,459 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// metamod.cpp - (main) implementation of metamod operations
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <malloc.h> // malloc, etc
|
||||
#include <errno.h> // errno, etc
|
||||
|
||||
#include <extdll.h> // always
|
||||
#include "enginecallbacks.h" // GET_GAME_DIR, etc
|
||||
|
||||
#include "metamod.h" // me
|
||||
#include "h_export.h" // GIVE_ENGINE_FUNCTIONS_FN, etc
|
||||
#include "mreg.h" // class mCmdList, etc
|
||||
#include "meta_api.h" // meta_globals_t, etc
|
||||
#include "mutil.h" // mutil_funcs_t, etc
|
||||
#include "osdep.h" // DLOPEN, getcwd, is_absolute_path,
|
||||
#include "reg_support.h" // meta_AddServerCommand, etc
|
||||
#include "game_support.h" // lookup_game, etc
|
||||
#include "commands_meta.h" // meta_register_cmdcvar, etc
|
||||
#include "thread_logparse.h" // logparse_handle, etc
|
||||
#include "support_meta.h" // valid_gamedir_file, etc
|
||||
#include "log_meta.h" // META_LOG, etc
|
||||
#include "types_meta.h" // mBOOL
|
||||
#include "info_name.h" // VNAME, etc
|
||||
#include "vdate.h" // COMPILE_TIME, etc
|
||||
#include "linkent.h"
|
||||
|
||||
cvar_t meta_version = {"metamod_version", VVERSION, FCVAR_SERVER, 0, NULL};
|
||||
|
||||
MConfig static_config;
|
||||
MConfig *Config=&static_config;
|
||||
option_t global_options[] = {
|
||||
{ "debuglevel", CF_INT, &Config->debuglevel, "0" },
|
||||
{ "gamedll", CF_PATH, &Config->gamedll, NULL },
|
||||
{ "plugins_file", CF_PATH, &Config->plugins_file, PLUGINS_INI },
|
||||
{ "exec_cfg", CF_STR, &Config->exec_cfg, EXEC_CFG },
|
||||
{ "autodetect", CF_BOOL, &Config->autodetect, "yes" },
|
||||
{ "clientmeta", CF_BOOL, &Config->clientmeta, "yes" },
|
||||
// list terminator
|
||||
{ NULL, CF_NONE, NULL, NULL }
|
||||
};
|
||||
|
||||
gamedll_t GameDLL;
|
||||
|
||||
meta_globals_t PublicMetaGlobals;
|
||||
meta_globals_t PrivateMetaGlobals;
|
||||
|
||||
meta_enginefuncs_t g_plugin_engfuncs;
|
||||
|
||||
MPluginList *Plugins;
|
||||
MRegCmdList *RegCmds;
|
||||
MRegCvarList *RegCvars;
|
||||
MRegMsgList *RegMsgs;
|
||||
|
||||
MPlayerList g_Players;
|
||||
int requestid_counter = 0;
|
||||
|
||||
DLHANDLE metamod_handle;
|
||||
int metamod_not_loaded = 0;
|
||||
|
||||
|
||||
// Very first metamod function that's run.
|
||||
// Do startup operations...
|
||||
int DLLINTERNAL metamod_startup(void) {
|
||||
char *cp, *mmfile=NULL, *cfile=NULL;
|
||||
|
||||
META_CONS(" ");
|
||||
META_CONS(" %s version %s Copyright (c) 2001-%s %s", VNAME, VVERSION, COPYRIGHT_YEAR, VAUTHOR);
|
||||
META_CONS(" Patch: %s v%d Copyright (c) 2004-%s %s", VPATCH_NAME, VPATCH_IVERSION, VPATCH_COPYRIGHT_YEAR, VPATCH_AUTHOR);
|
||||
META_CONS(" %s comes with ABSOLUTELY NO WARRANTY; for details type `meta gpl'.", VNAME);
|
||||
META_CONS(" This is free software, and you are welcome to redistribute it");
|
||||
META_CONS(" under certain conditions; type `meta gpl' for details.");
|
||||
META_CONS(" ");
|
||||
|
||||
META_LOG("%s v%s %s", VNAME, VVERSION, VDATE);
|
||||
META_LOG("by %s", VAUTHOR);
|
||||
META_LOG(" %s", VURL);
|
||||
META_LOG(" Patch: %s v%d", VPATCH_NAME, VPATCH_IVERSION);
|
||||
META_LOG(" by %s", VPATCH_AUTHOR);
|
||||
META_LOG(" %s", VPATCH_WEBSITE);
|
||||
META_LOG("compiled: %s %s (%s)", COMPILE_TIME, COMPILE_TZONE, OPT_TYPE);
|
||||
|
||||
// If running with "+developer", allow an opportunity to break in with
|
||||
// a debugger.
|
||||
if((int)CVAR_GET_FLOAT("developer") != 0)
|
||||
sleep(1);
|
||||
|
||||
// Get gamedir, very early on, because it seems we need it all over the
|
||||
// place here at the start.
|
||||
if(!meta_init_gamedll()) {
|
||||
META_ERROR("Failure to init game DLL; exiting...");
|
||||
return(0);
|
||||
}
|
||||
|
||||
// Register various console commands and cvars.
|
||||
// Can I do these here, rather than waiting for GameDLLInit() ?
|
||||
// Looks like it works okay..
|
||||
meta_register_cmdcvar();
|
||||
{
|
||||
//dirty hacks
|
||||
int vers[4] = {RC_VERS_DWORD};
|
||||
char mvers[32];
|
||||
|
||||
if(vers[2]==0)
|
||||
safevoid_snprintf(mvers, sizeof(mvers), "%d.%dp%d", vers[0], vers[1], vers[3]);
|
||||
else
|
||||
safevoid_snprintf(mvers, sizeof(mvers), "%d.%d.%dp%d", vers[0], vers[1], vers[2], vers[3]);
|
||||
|
||||
CVAR_SET_STRING(meta_version.name, mvers);
|
||||
}
|
||||
|
||||
// Set a slight debug level for developer mode, if debug level not
|
||||
// already set.
|
||||
if((int)CVAR_GET_FLOAT("developer") != 0 && (int)meta_debug.value == 0) {
|
||||
CVAR_SET_FLOAT("meta_debug", (float)(meta_debug_value = 3));
|
||||
}
|
||||
|
||||
// Init default values
|
||||
Config->init(global_options);
|
||||
// Find config file
|
||||
cfile=CONFIG_INI;
|
||||
if((cp=LOCALINFO("mm_configfile")) && *cp != '\0') {
|
||||
META_LOG("Configfile specified via localinfo: %s", cp);
|
||||
if(valid_gamedir_file(cp))
|
||||
cfile=cp;
|
||||
else
|
||||
META_WARNING("Empty/missing config.ini file: %s; falling back to %s",
|
||||
cp, cfile);
|
||||
}
|
||||
// Load config file
|
||||
if(valid_gamedir_file(cfile))
|
||||
Config->load(cfile);
|
||||
else
|
||||
META_DEBUG(2, ("No config.ini file found: %s", CONFIG_INI));
|
||||
|
||||
// Now, override config options with localinfo commandline options.
|
||||
if((cp=LOCALINFO("mm_debug")) && *cp != '\0') {
|
||||
META_LOG("Debuglevel specified via localinfo: %s", cp);
|
||||
Config->set("debuglevel", cp);
|
||||
}
|
||||
if((cp=LOCALINFO("mm_gamedll")) && *cp != '\0') {
|
||||
META_LOG("Gamedll specified via localinfo: %s", cp);
|
||||
Config->set("gamedll", cp);
|
||||
}
|
||||
if((cp=LOCALINFO("mm_pluginsfile")) && *cp != '\0') {
|
||||
META_LOG("Pluginsfile specified via localinfo: %s", cp);
|
||||
Config->set("plugins_file", cp);
|
||||
}
|
||||
if((cp=LOCALINFO("mm_execcfg")) && *cp != '\0') {
|
||||
META_LOG("Execcfg specified via localinfo: %s", cp);
|
||||
Config->set("exec_cfg", cp);
|
||||
}
|
||||
if((cp=LOCALINFO("mm_autodetect")) && *cp != '\0') {
|
||||
META_LOG("Autodetect specified via localinfo: %s", cp);
|
||||
Config->set("autodetect", cp);
|
||||
}
|
||||
if((cp=LOCALINFO("mm_clientmeta")) && *cp != '\0') {
|
||||
META_LOG("Clientmeta specified via localinfo: %s", cp);
|
||||
Config->set("clientmeta", cp);
|
||||
}
|
||||
|
||||
|
||||
// Check for an initial debug level, since cfg files don't get exec'd
|
||||
// until later.
|
||||
if(Config->debuglevel != 0) {
|
||||
CVAR_SET_FLOAT("meta_debug", (float)(meta_debug_value = Config->debuglevel));
|
||||
}
|
||||
|
||||
// Prepare for registered commands from plugins.
|
||||
RegCmds = new MRegCmdList();
|
||||
RegCvars = new MRegCvarList();
|
||||
|
||||
// Prepare for registered user messages from gamedll.
|
||||
RegMsgs = new MRegMsgList();
|
||||
|
||||
// Copy, and store pointer in Engine struct. Yes, we could just store
|
||||
// the actual engine_t struct in Engine, but then it wouldn't be a
|
||||
// pointer to match the other g_engfuncs.
|
||||
g_plugin_engfuncs.set_from(Engine.funcs);
|
||||
Engine.pl_funcs=&g_plugin_engfuncs;
|
||||
// substitute our special versions of various commands
|
||||
Engine.pl_funcs->pfnAddServerCommand = meta_AddServerCommand;
|
||||
Engine.pl_funcs->pfnCVarRegister = meta_CVarRegister;
|
||||
Engine.pl_funcs->pfnCvar_RegisterVariable = meta_CVarRegister;
|
||||
Engine.pl_funcs->pfnRegUserMsg = meta_RegUserMsg;
|
||||
if(IS_VALID_PTR((void*)Engine.pl_funcs->pfnQueryClientCvarValue))
|
||||
Engine.pl_funcs->pfnQueryClientCvarValue = meta_QueryClientCvarValue;
|
||||
else
|
||||
Engine.pl_funcs->pfnQueryClientCvarValue = NULL;
|
||||
if(!IS_VALID_PTR((void*)Engine.pl_funcs->pfnQueryClientCvarValue2))
|
||||
Engine.pl_funcs->pfnQueryClientCvarValue2 = NULL;
|
||||
|
||||
// Before, we loaded plugins before loading the game DLL, so that if no
|
||||
// plugins caught engine functions, we could pass engine funcs straight
|
||||
// to game dll, rather than acting as intermediary. (Should perform
|
||||
// better, right?)
|
||||
//
|
||||
// But since a plugin can be loaded at any time, we have to go ahead
|
||||
// and catch the engine funcs regardless. Also, we want to give each
|
||||
// plugin a copy of the gameDLL's api tables, in case they need to call
|
||||
// API functions directly.
|
||||
//
|
||||
// Thus, load gameDLL first, then plugins.
|
||||
//
|
||||
// However, we have to init the Plugins object first, because if the
|
||||
// gamedll calls engine functions during GiveFnptrsToDll (like hpb_bot
|
||||
// does) then it needs to be non-null so META_ENGINE_HANDLE won't crash.
|
||||
//
|
||||
// However, having replaced valid_file with valid_gamedir_file, we need
|
||||
// to at least initialize the gameDLL to include the gamedir, before
|
||||
// looking for plugins.ini.
|
||||
//
|
||||
// In fact, we need gamedir even earlier, so moved up above.
|
||||
|
||||
// Fall back to old plugins filename, if configured one isn't found.
|
||||
mmfile=PLUGINS_INI;
|
||||
if(!valid_gamedir_file(PLUGINS_INI) && valid_gamedir_file(OLD_PLUGINS_INI))
|
||||
mmfile=OLD_PLUGINS_INI;
|
||||
if(valid_gamedir_file(Config->plugins_file))
|
||||
mmfile=Config->plugins_file;
|
||||
else
|
||||
META_WARNING("Plugins file is empty/missing: %s; falling back to %s",
|
||||
Config->plugins_file, mmfile);
|
||||
|
||||
Plugins = new MPluginList(mmfile);
|
||||
|
||||
if(!meta_load_gamedll()) {
|
||||
META_ERROR("Failure to load game DLL; exiting...");
|
||||
return(0);
|
||||
}
|
||||
if(!Plugins->load()) {
|
||||
META_WARNING("Failure to load plugins...");
|
||||
// Exit on failure here? Dunno...
|
||||
}
|
||||
|
||||
// Allow for commands to metamod plugins at startup. Autoexec.cfg is
|
||||
// read too early, and server.cfg is read too late.
|
||||
//
|
||||
// Only attempt load if the file appears to exist and be non-empty, to
|
||||
// avoid confusing users with "couldn't exec exec.cfg" console
|
||||
// messages.
|
||||
if(valid_gamedir_file(Config->exec_cfg))
|
||||
mmfile=Config->exec_cfg;
|
||||
else if(valid_gamedir_file(OLD_EXEC_CFG))
|
||||
mmfile=OLD_EXEC_CFG;
|
||||
else
|
||||
mmfile=NULL;
|
||||
|
||||
if(mmfile) {
|
||||
if(mmfile[0]=='/')
|
||||
META_WARNING("Cannot exec absolute pathnames: %s", mmfile);
|
||||
else {
|
||||
char cmd[NAME_MAX];
|
||||
META_LOG("Exec'ing metamod exec.cfg: %s...", mmfile);
|
||||
safevoid_snprintf(cmd, sizeof(cmd), "exec %s\n", mmfile);
|
||||
SERVER_COMMAND(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
// Set initial GameDLL fields (name, gamedir).
|
||||
// meta_errno values:
|
||||
// - ME_NULLRESULT getcwd failed
|
||||
mBOOL DLLINTERNAL meta_init_gamedll(void) {
|
||||
char gamedir[PATH_MAX];
|
||||
char *cp;
|
||||
|
||||
memset(&GameDLL, 0, sizeof(GameDLL));
|
||||
|
||||
GET_GAME_DIR(gamedir);
|
||||
normalize_pathname(gamedir);
|
||||
//
|
||||
// As of 1.1.1.1, the engine routine GET_GAME_DIR no longer returns a
|
||||
// full-pathname, but rather just the path specified as the argument to
|
||||
// "-game".
|
||||
//
|
||||
// However, since we have to work properly under both the new version
|
||||
// as well as previous versions, we have to support both possibilities.
|
||||
//
|
||||
// Note: the code has always assumed the server op wouldn't do:
|
||||
// hlds -game other/firearms
|
||||
//
|
||||
if(is_absolute_path(gamedir)) {
|
||||
// Old style; GET_GAME_DIR returned full pathname. Copy this into
|
||||
// our gamedir, and truncate to get the game name.
|
||||
// (note check for both linux and win32 full pathname.)
|
||||
STRNCPY(GameDLL.gamedir, gamedir, sizeof(GameDLL.gamedir));
|
||||
cp=strrchr(gamedir, '/') + 1;
|
||||
STRNCPY(GameDLL.name, cp, sizeof(GameDLL.name));
|
||||
}
|
||||
else {
|
||||
// New style; GET_GAME_DIR returned game name. Copy this into our
|
||||
// game name, and prepend the current working directory.
|
||||
char buf[PATH_MAX];
|
||||
if(!getcwd(buf, sizeof(buf))) {
|
||||
META_WARNING("dll: Couldn't get cwd; %s", strerror(errno));
|
||||
RETURN_ERRNO(mFALSE, ME_NULLRESULT);
|
||||
}
|
||||
safevoid_snprintf(GameDLL.gamedir, sizeof(GameDLL.gamedir),
|
||||
"%s/%s", buf, gamedir);
|
||||
STRNCPY(GameDLL.name, gamedir, sizeof(GameDLL.name));
|
||||
}
|
||||
|
||||
META_DEBUG(3, ("Game: %s", GameDLL.name));
|
||||
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
// Load game DLL.
|
||||
// meta_errno values:
|
||||
// - ME_DLOPEN couldn't dlopen game dll file
|
||||
// - ME_DLMISSING couldn't find required routine in game dll
|
||||
// (GiveFnptrsToDll, GetEntityAPI, GetEntityAPI2)
|
||||
mBOOL DLLINTERNAL meta_load_gamedll(void) {
|
||||
int iface_vers;
|
||||
int found=0;
|
||||
|
||||
GIVE_ENGINE_FUNCTIONS_FN pfn_give_engfuncs;
|
||||
GETNEWDLLFUNCTIONS_FN pfn_getapinew;
|
||||
GETENTITYAPI2_FN pfn_getapi2;
|
||||
GETENTITYAPI_FN pfn_getapi;
|
||||
|
||||
if(!setup_gamedll(&GameDLL)) {
|
||||
META_WARNING("dll: Unrecognized game: %s", GameDLL.name);
|
||||
// meta_errno should be already set in lookup_game()
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
// open the game DLL
|
||||
if(!(GameDLL.handle=DLOPEN(GameDLL.pathname))) {
|
||||
META_WARNING("dll: Couldn't load game DLL %s: %s", GameDLL.pathname,
|
||||
DLERROR());
|
||||
RETURN_ERRNO(mFALSE, ME_DLOPEN);
|
||||
}
|
||||
|
||||
// Used to only pass our table of engine funcs if a loaded plugin
|
||||
// wanted to catch one of the functions, but now that plugins are
|
||||
// dynamically loadable at any time, we have to always pass our table,
|
||||
// so that any plugin loaded later can catch what they need to.
|
||||
if((pfn_give_engfuncs = (GIVE_ENGINE_FUNCTIONS_FN) DLSYM(GameDLL.handle, "GiveFnptrsToDll")))
|
||||
{
|
||||
pfn_give_engfuncs(&meta_engfuncs, gpGlobals);
|
||||
META_DEBUG(3, ("dll: Game '%s': Called GiveFnptrsToDll",
|
||||
GameDLL.name));
|
||||
|
||||
//activate linkent-replacement after give_engfuncs so that if game dll is
|
||||
//plugin too and uses same method we get combined export table of plugin
|
||||
//and game dll
|
||||
if(!init_linkent_replacement(metamod_handle, GameDLL.handle)) {
|
||||
META_WARNING("dll: Couldn't load linkent replacement for game DLL");
|
||||
RETURN_ERRNO(mFALSE, ME_DLERROR);
|
||||
}
|
||||
}
|
||||
else {
|
||||
META_WARNING("dll: Couldn't find GiveFnptrsToDll() in game DLL '%s': %s",
|
||||
GameDLL.name, DLERROR());
|
||||
RETURN_ERRNO(mFALSE, ME_DLMISSING);
|
||||
}
|
||||
|
||||
// Yes...another macro.
|
||||
#define GET_FUNC_TABLE_FROM_GAME(gamedll, pfnGetFuncs, STR_GetFuncs, struct_field, API_TYPE, TABLE_TYPE, vers_pass, vers_int, vers_want, gotit) \
|
||||
if((pfnGetFuncs = (API_TYPE) DLSYM(gamedll.handle, STR_GetFuncs))) { \
|
||||
gamedll.funcs.struct_field = (TABLE_TYPE*) calloc(1, sizeof(TABLE_TYPE)); \
|
||||
if(!gamedll.funcs.struct_field) {\
|
||||
META_WARNING("malloc failed for gamedll struct_field: %s", STR_GetFuncs); \
|
||||
} \
|
||||
else if(pfnGetFuncs(gamedll.funcs.struct_field, vers_pass)) { \
|
||||
META_DEBUG(3, ("dll: Game '%s': Found %s", gamedll.name, STR_GetFuncs)); \
|
||||
gotit=1; \
|
||||
} \
|
||||
else { \
|
||||
META_WARNING("dll: Failure calling %s in game '%s'", STR_GetFuncs, gamedll.name); \
|
||||
free(gamedll.funcs.struct_field); \
|
||||
gamedll.funcs.struct_field=NULL; \
|
||||
if(vers_int != vers_want) { \
|
||||
META_WARNING("dll: Interface version didn't match; we wanted %d, they had %d", vers_want, vers_int); \
|
||||
/* reproduce error from engine */ \
|
||||
META_CONS("=================="); \
|
||||
META_CONS("Game DLL version mismatch"); \
|
||||
META_CONS("DLL version is %d, engine version is %d", vers_int, vers_want); \
|
||||
if(vers_int > vers_want) \
|
||||
META_CONS("Engine appears to be outdated, check for updates"); \
|
||||
else \
|
||||
META_CONS("The game DLL for %s appears to be outdated, check for updates", GameDLL.name); \
|
||||
META_CONS("=================="); \
|
||||
ALERT(at_error, "Exiting...\n"); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else { \
|
||||
META_DEBUG(5, ("dll: Game '%s': No %s", gamedll.name, STR_GetFuncs)); \
|
||||
gamedll.funcs.struct_field=NULL; \
|
||||
}
|
||||
|
||||
// Look for API-NEW interface in Game dll. We do this before API2/API, because
|
||||
// that's what the engine appears to do..
|
||||
iface_vers=NEW_DLL_FUNCTIONS_VERSION;
|
||||
GET_FUNC_TABLE_FROM_GAME(GameDLL, pfn_getapinew, "GetNewDLLFunctions", newapi_table,
|
||||
GETNEWDLLFUNCTIONS_FN, meta_new_dll_functions_t,
|
||||
&iface_vers, iface_vers, NEW_DLL_FUNCTIONS_VERSION, found);
|
||||
|
||||
// Look for API2 interface in plugin; preferred over API-1.
|
||||
found=0;
|
||||
iface_vers=INTERFACE_VERSION;
|
||||
GET_FUNC_TABLE_FROM_GAME(GameDLL, pfn_getapi2, "GetEntityAPI2", dllapi_table,
|
||||
GETENTITYAPI2_FN, DLL_FUNCTIONS,
|
||||
&iface_vers, iface_vers, INTERFACE_VERSION, found);
|
||||
|
||||
// Look for API-1 in plugin, if API2 interface wasn't found.
|
||||
if(!found) {
|
||||
found=0;
|
||||
GET_FUNC_TABLE_FROM_GAME(GameDLL, pfn_getapi, "GetEntityAPI", dllapi_table,
|
||||
GETENTITYAPI_FN, DLL_FUNCTIONS,
|
||||
INTERFACE_VERSION, INTERFACE_VERSION, INTERFACE_VERSION, found);
|
||||
}
|
||||
|
||||
// If didn't find either, return failure.
|
||||
if(!found) {
|
||||
META_WARNING("dll: Couldn't find either GetEntityAPI nor GetEntityAPI2 in game DLL '%s'", GameDLL.name);
|
||||
RETURN_ERRNO(mFALSE, ME_DLMISSING);
|
||||
}
|
||||
|
||||
META_LOG("Game DLL for '%s' loaded successfully", GameDLL.desc);
|
||||
return(mTRUE);
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
LIBRARY metamod
|
||||
EXPORTS
|
||||
GiveFnptrsToDll @1
|
||||
SECTIONS
|
||||
.data READ WRITE
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "metamod", "metamod.vcproj", "{02832A39-E902-46B7-8D47-911C37CF41B0}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{02832A39-E902-46B7-8D47-911C37CF41B0}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{02832A39-E902-46B7-8D47-911C37CF41B0}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{02832A39-E902-46B7-8D47-911C37CF41B0}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{02832A39-E902-46B7-8D47-911C37CF41B0}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,489 +0,0 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8,00"
|
||||
Name="metamod"
|
||||
ProjectGUID="{02832A39-E902-46B7-8D47-911C37CF41B0}"
|
||||
RootNamespace="metamod"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="0"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="../../hlsdk/common ../../hlsdk/dlls ../../hlsdk/engine ../../hlsdk/pm_shared"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;METAMOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;__METAMOD_BUILD__"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="2"
|
||||
ModuleDefinitionFile="metamod.def"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="0"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="..\hlsdk\common;..\hlsdk\dlls;..\hlsdk\engine;..\hlsdk\pm_shared;."
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;METAMOD_EXPORTS;_CRT_SECURE_NO_DEPRECATE;__METAMOD_BUILD__"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="false"
|
||||
DebugInformationFormat="0"
|
||||
CompileAs="0"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="false"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\api_hook.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\api_info.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\commands_meta.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\conf_meta.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dllapi.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\engine_api.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\engineinfo.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\game_autodetect.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\game_support.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\h_export.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\linkgame.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\linkplug.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\log_meta.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta_eiface.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\metamod.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mhook.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mlist.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mplayer.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mplugin.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mqueue.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mreg.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mutil.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\osdep.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\osdep_detect_gamedll_win32.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\osdep_linkent_win32.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\osdep_p.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\reg_support.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\sdk_util.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\studioapi.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\support_meta.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\thread_logparse.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vdate.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\api_hook.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\api_info.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\commands_meta.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\comp_dep.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\conf_meta.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dllapi.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\engine_api.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\engineinfo.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\game_autodetect.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\game_support.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\games.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\h_export.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\info_name.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\linkent.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\log_meta.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta_api.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta_eiface.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\metamod.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mhook.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mlist.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mm_pextensions.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mplayer.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mplugin.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mqueue.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mreg.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\mutil.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\new_baseclass.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\osdep.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\osdep_p.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\plinfo.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\reg_support.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ret_type.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\sdk_util.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\studioapi.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\support_meta.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\thread_logparse.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tqueue.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\types_meta.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vdate.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\vers_meta.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\res_meta.rc"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -1,901 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// mlist.cpp - functions for list of plugins (class MPluginList)
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <errno.h> // errno, etc
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "mlist.h" // me
|
||||
#include "mplugin.h" // class MPlugin
|
||||
#include "plinfo.h" // plid_t, etc
|
||||
#include "commands_meta.h" // cmd_meta_pluginlist, etc
|
||||
#include "metamod.h" // GameDLL, etc
|
||||
#include "types_meta.h" // mBOOL
|
||||
#include "log_meta.h" // META_LOG, etc
|
||||
#include "osdep.h" // win32 snprintf, normalize_pathname,
|
||||
#include "osdep_p.h"
|
||||
|
||||
// Constructor
|
||||
MPluginList::MPluginList(const char *ifile)
|
||||
: size(MAX_PLUGINS), endlist(0)
|
||||
{
|
||||
int i;
|
||||
// store filename of ini file
|
||||
STRNCPY(inifile, ifile, sizeof(inifile));
|
||||
// initialize array
|
||||
for(i=0; i < size; i++) {
|
||||
//reset to empty
|
||||
plist[i].index=i+1;
|
||||
reset_plugin(&plist[i]);
|
||||
}
|
||||
endlist=0;
|
||||
}
|
||||
|
||||
// Resets plugin to empty
|
||||
void DLLINTERNAL MPluginList::reset_plugin(MPlugin *pl_find) {
|
||||
int i;
|
||||
|
||||
//calculate index
|
||||
i = pl_find - &plist[0];
|
||||
|
||||
//free any pointers first
|
||||
pl_find->free_api_pointers();
|
||||
|
||||
//set zero
|
||||
memset(pl_find, 0, sizeof(*pl_find));
|
||||
|
||||
pl_find->index=i+1; // 1-based
|
||||
}
|
||||
|
||||
// Find a plugin based on the plugin index #.
|
||||
// meta_errno values:
|
||||
// - ME_ARGUMENT invalid pindex
|
||||
// - ME_NOTFOUND couldn't find a matching plugin
|
||||
MPlugin * DLLINTERNAL MPluginList::find(int pindex) {
|
||||
MPlugin *pfound;
|
||||
if(pindex <= 0)
|
||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
||||
pfound=&plist[pindex-1];
|
||||
if(pfound->status < PL_VALID)
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
else
|
||||
return(pfound);
|
||||
}
|
||||
|
||||
// Find a plugin based on the plugin handle.
|
||||
// meta_errno values:
|
||||
// - ME_ARGUMENT invalid pindex
|
||||
// - ME_NOTFOUND couldn't find a matching plugin
|
||||
MPlugin * DLLINTERNAL MPluginList::find(DLHANDLE handle) {
|
||||
int i;
|
||||
|
||||
if(!handle)
|
||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
||||
for(i=0; i < endlist; i++) {
|
||||
if(plist[i].status < PL_VALID)
|
||||
continue;
|
||||
if(plist[i].handle == handle)
|
||||
return(&plist[i]);
|
||||
}
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
// Clear source_plugin_index on all matching plugins
|
||||
void DLLINTERNAL MPluginList::clear_source_plugin_index(int source_index) {
|
||||
int i;
|
||||
|
||||
if(source_index <= 0)
|
||||
return;
|
||||
|
||||
for(i=0; i < endlist; i++) {
|
||||
if(plist[i].status < PL_VALID)
|
||||
continue;
|
||||
if(plist[i].source_plugin_index == source_index)
|
||||
plist[i].source_plugin_index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Find if any plugin has been loaded by plugin 'source_index'
|
||||
mBOOL DLLINTERNAL MPluginList::found_child_plugins(int source_index) {
|
||||
int i;
|
||||
|
||||
if(source_index <= 0)
|
||||
return(mFALSE);
|
||||
|
||||
for(i=0; i < endlist; i++) {
|
||||
if(plist[i].status < PL_VALID)
|
||||
continue;
|
||||
if(plist[i].source_plugin_index == source_index)
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
// Try make endlist lower (called after plugin unload)
|
||||
void DLLINTERNAL MPluginList::trim_list(void) {
|
||||
int i,n;
|
||||
|
||||
if(endlist <= 0)
|
||||
return;
|
||||
|
||||
for(i=0,n=0; i < endlist; i++) {
|
||||
if(plist[i].status == PL_EMPTY)
|
||||
continue;
|
||||
n=i+1;
|
||||
}
|
||||
|
||||
if(n < endlist)
|
||||
endlist=n;
|
||||
}
|
||||
|
||||
// Find a plugin with the given plid.
|
||||
// meta_errno values:
|
||||
// - ME_ARGUMENT null plid_t
|
||||
// - ME_NOTFOUND couldn't find a matching plugin
|
||||
MPlugin * DLLINTERNAL MPluginList::find(plid_t id) {
|
||||
int i;
|
||||
|
||||
if(!id)
|
||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
||||
for(i=0; i < endlist; i++) {
|
||||
if(plist[i].status < PL_VALID)
|
||||
continue;
|
||||
if(plist[i].info == id)
|
||||
return(&plist[i]);
|
||||
}
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
// Find a plugin with the given pathname.
|
||||
// meta_errno values:
|
||||
// - ME_ARGUMENT null path
|
||||
// - ME_NOTFOUND couldn't find a matching plugin
|
||||
MPlugin * DLLINTERNAL MPluginList::find(const char *findpath) {
|
||||
int i;
|
||||
|
||||
if(!findpath)
|
||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
||||
META_DEBUG(8, ("Looking for loaded plugin with dlfnamepath: %s", findpath));
|
||||
for(i=0; i < endlist; i++) {
|
||||
META_DEBUG(9, ("Looking at: plugin %s loadedpath: %s", plist[i].file, plist[i].pathname));
|
||||
if(plist[i].status < PL_VALID)
|
||||
continue;
|
||||
if(strmatch(plist[i].pathname, findpath)) {
|
||||
META_DEBUG(8, ("Found loaded plugin %s", plist[i].file));
|
||||
return(&plist[i]);
|
||||
}
|
||||
}
|
||||
META_DEBUG(8, ("No loaded plugin found with path: %s", findpath));
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
// Find a plugin that uses the given memory location.
|
||||
// meta_errno values:
|
||||
// - ME_ARGUMENT null memptr
|
||||
// - ME_NOTFOUND couldn't find a matching plugin
|
||||
// - errno's from DLFNAME()
|
||||
MPlugin * DLLINTERNAL MPluginList::find_memloc(void *memptr) {
|
||||
#ifdef linux
|
||||
const char *dlfile;
|
||||
|
||||
if(!memptr)
|
||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
||||
if(!(dlfile=DLFNAME(memptr))) {
|
||||
META_DEBUG(8, ("DLFNAME failed to find memloc %d", memptr));
|
||||
// meta_errno should be already set in DLFNAME
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(find(dlfile));
|
||||
#else
|
||||
DLHANDLE dlhandle;
|
||||
|
||||
if(!memptr)
|
||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
||||
if(!(dlhandle=get_module_handle_of_memptr(memptr))) {
|
||||
META_DEBUG(8, ("DLFNAME failed to find memloc %d", memptr));
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
return(find(dlhandle));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Find a plugin with non-ambiguous prefix string matching desc, file,
|
||||
// name, or logtag.
|
||||
// meta_errno values:
|
||||
// - ME_ARGUMENT null prefix
|
||||
// - ME_NOTFOUND couldn't find a matching plugin
|
||||
// - ME_NOTUNIQ found multiple matches; no unique match
|
||||
MPlugin * DLLINTERNAL MPluginList::find_match(const char *prefix) {
|
||||
int i, len;
|
||||
MPlugin *iplug, *pfound;
|
||||
char buf[NAME_MAX];
|
||||
|
||||
if(!prefix)
|
||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
||||
pfound=NULL;
|
||||
len=strlen(prefix);
|
||||
safevoid_snprintf(buf, sizeof(buf), "mm_%s", prefix);
|
||||
for(i=0; i < endlist; i++) {
|
||||
iplug=&plist[i];
|
||||
if(iplug->status < PL_VALID)
|
||||
continue;
|
||||
if(iplug->info && strncasecmp(iplug->info->name, prefix, len) == 0) {
|
||||
if(pfound)
|
||||
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
||||
pfound=iplug;
|
||||
continue;
|
||||
}
|
||||
else if(strncasecmp(iplug->desc, prefix, len) == 0) {
|
||||
if(pfound)
|
||||
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
||||
pfound=iplug;
|
||||
continue;
|
||||
}
|
||||
else if(strncasecmp(iplug->file, prefix, len) == 0) {
|
||||
if(pfound)
|
||||
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
||||
pfound=iplug;
|
||||
continue;
|
||||
}
|
||||
else if(strncasecmp(iplug->file, buf, strlen(buf)) == 0) {
|
||||
if(pfound)
|
||||
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
||||
pfound=iplug;
|
||||
continue;
|
||||
}
|
||||
else if(iplug->info
|
||||
&& strncasecmp(iplug->info->logtag, prefix, len) == 0)
|
||||
{
|
||||
if(pfound)
|
||||
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
||||
pfound=iplug;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if(pfound)
|
||||
return(pfound);
|
||||
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
// Find a plugin with same file, logtag, desc or significant
|
||||
// prefix of file. Uses the platform_match() method of MPlugin.
|
||||
// meta_errno values:
|
||||
// - ME_ARGUMENT null prefix
|
||||
// - ME_NOTFOUND couldn't find a matching plugin
|
||||
MPlugin * DLLINTERNAL MPluginList::find_match(MPlugin *pmatch) {
|
||||
int i;
|
||||
MPlugin *iplug, *pfound;
|
||||
if(!pmatch)
|
||||
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
||||
pfound=NULL;
|
||||
for(i=0; i < endlist; i++) {
|
||||
iplug=&plist[i];
|
||||
if(pmatch->platform_match(iplug)) {
|
||||
pfound=iplug;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(pfound)
|
||||
return(pfound);
|
||||
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
// Add a plugin to the list.
|
||||
// meta_errno values:
|
||||
// - ME_MAXREACHED reached max plugins
|
||||
MPlugin * DLLINTERNAL MPluginList::add(MPlugin *padd) {
|
||||
int i;
|
||||
MPlugin *iplug;
|
||||
|
||||
// Find either:
|
||||
// - a slot in the list that's not being used
|
||||
// - the end of the list
|
||||
for(i=0; i < endlist && plist[i].status != PL_EMPTY; i++);
|
||||
|
||||
// couldn't find a slot to use
|
||||
if(i==size) {
|
||||
META_WARNING("Couldn't add plugin '%s' to list; reached max plugins (%d)",
|
||||
padd->file, i);
|
||||
RETURN_ERRNO(NULL, ME_MAXREACHED);
|
||||
}
|
||||
|
||||
// if we found the end of the list, advance end marker
|
||||
if(i==endlist)
|
||||
endlist++;
|
||||
iplug = &plist[i];
|
||||
|
||||
// copy filename into this free slot
|
||||
STRNCPY(iplug->filename, padd->filename, sizeof(iplug->filename));
|
||||
// Copy file offset ptr.
|
||||
// Can't just copy ptr, as it points to offset in padd, which will go
|
||||
// away; need to point to corresponding offset in iplug.
|
||||
iplug->file = iplug->filename + (padd->file - padd->filename);
|
||||
// copy description
|
||||
STRNCPY(iplug->desc, padd->desc, sizeof(iplug->desc));
|
||||
// copy pathname
|
||||
STRNCPY(iplug->pathname, padd->pathname, sizeof(iplug->pathname));
|
||||
// copy source
|
||||
iplug->source=padd->source;
|
||||
// copy loader-plugin
|
||||
iplug->source_plugin_index=padd->source_plugin_index;
|
||||
// copy status
|
||||
iplug->status=padd->status;
|
||||
|
||||
return(iplug);
|
||||
}
|
||||
|
||||
|
||||
// Read plugins.ini at server startup.
|
||||
// meta_errno values:
|
||||
// - ME_NOFILE ini file missing or empty
|
||||
mBOOL DLLINTERNAL MPluginList::ini_startup() {
|
||||
FILE *fp;
|
||||
char line[MAX_STRBUF_LEN];
|
||||
int n, ln;
|
||||
MPlugin *pmatch;
|
||||
|
||||
if(!valid_gamedir_file(inifile)) {
|
||||
META_WARNING("ini: Metamod plugins file empty or missing: %s", inifile);
|
||||
RETURN_ERRNO(mFALSE, ME_NOFILE);
|
||||
}
|
||||
full_gamedir_path(inifile, inifile);
|
||||
|
||||
fp=fopen(inifile, "r");
|
||||
if(!fp) {
|
||||
META_WARNING("ini: Unable to open plugins file '%s': %s", inifile,
|
||||
strerror(errno));
|
||||
RETURN_ERRNO(mFALSE, ME_NOFILE);
|
||||
}
|
||||
|
||||
META_LOG("ini: Begin reading plugins list: %s", inifile);
|
||||
for(n=0, ln=1; !feof(fp) && fgets(line, sizeof(line), fp) && n < size; ln++) {
|
||||
// Remove line terminations.
|
||||
char *cp;
|
||||
if((cp=strrchr(line, '\r')))
|
||||
*cp='\0';
|
||||
if((cp=strrchr(line, '\n')))
|
||||
*cp='\0';
|
||||
// Parse directly into next entry in array
|
||||
if(!plist[n].ini_parseline(line)) {
|
||||
if(meta_errno==ME_FORMAT)
|
||||
META_WARNING("ini: Skipping malformed line %d of %s", ln,
|
||||
inifile);
|
||||
continue;
|
||||
}
|
||||
// Check for a duplicate - an existing entry with this pathname.
|
||||
if(find(plist[n].pathname)) {
|
||||
// Should we check platform specific level here?
|
||||
META_INFO("ini: Skipping duplicate plugin, line %d of %s: %s",
|
||||
ln, inifile, plist[n].pathname);
|
||||
continue;
|
||||
}
|
||||
// Check for a matching platform with different platform specifics
|
||||
// level.
|
||||
if(NULL != (pmatch=find_match(&plist[n]))) {
|
||||
if(pmatch->pfspecific >= plist[n].pfspecific) {
|
||||
META_DEBUG(1, ("ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)",
|
||||
ln, inifile, pmatch->pfspecific, plist[n].pfspecific));
|
||||
continue;
|
||||
}
|
||||
META_DEBUG(1, ("ini: Plugin in line %d overrides existing plugin with lower platform specific level %d, ours %d",
|
||||
ln, pmatch->pfspecific, plist[n].pfspecific));
|
||||
//reset to empty
|
||||
reset_plugin(pmatch);
|
||||
}
|
||||
plist[n].action=PA_LOAD;
|
||||
META_LOG("ini: Read plugin config for: %s", plist[n].desc);
|
||||
n++;
|
||||
endlist=n; // mark end of list
|
||||
}
|
||||
META_LOG("ini: Finished reading plugins list: %s; Found %d plugins to load",
|
||||
inifile, n);
|
||||
|
||||
fclose(fp);
|
||||
if(!n) {
|
||||
META_WARNING("ini: Warning; no plugins found to load?");
|
||||
}
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
// Re-read plugins.ini looking for added/deleted/changed plugins.
|
||||
// meta_errno values:
|
||||
// - ME_NOFILE ini file missing or empty
|
||||
mBOOL DLLINTERNAL MPluginList::ini_refresh() {
|
||||
FILE *fp;
|
||||
char line[MAX_STRBUF_LEN];
|
||||
int n, ln;
|
||||
MPlugin pl_temp;
|
||||
MPlugin *pl_found, *pl_added;
|
||||
|
||||
fp=fopen(inifile, "r");
|
||||
if(!fp) {
|
||||
META_WARNING("ini: Unable to open plugins file '%s': %s", inifile,
|
||||
strerror(errno));
|
||||
RETURN_ERRNO(mFALSE, ME_NOFILE);
|
||||
}
|
||||
|
||||
META_LOG("ini: Begin re-reading plugins list: %s", inifile);
|
||||
for(n=0, ln=1; !feof(fp) && fgets(line, sizeof(line), fp) && n < size; ln++)
|
||||
{
|
||||
// Remove line terminations.
|
||||
char *cp;
|
||||
if((cp=strrchr(line, '\r')))
|
||||
*cp='\0';
|
||||
if((cp=strrchr(line, '\n')))
|
||||
*cp='\0';
|
||||
// Parse into a temp plugin
|
||||
memset(&pl_temp, 0, sizeof(pl_temp));
|
||||
if(!pl_temp.ini_parseline(line)) {
|
||||
if(meta_errno==ME_FORMAT)
|
||||
META_WARNING("ini: Skipping malformed line %d of %s",
|
||||
ln, inifile);
|
||||
continue;
|
||||
}
|
||||
// Try to find plugin with this pathname in the current list of
|
||||
// plugins.
|
||||
if(!(pl_found=find(pl_temp.pathname))) {
|
||||
// Check for a matching platform with higher platform specifics
|
||||
// level.
|
||||
if(NULL != (pl_found=find_match(&pl_temp))) {
|
||||
if(pl_found->pfspecific >= pl_temp.pfspecific) {
|
||||
META_DEBUG(1, ("ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)",
|
||||
ln, inifile, pl_found->pfspecific, pl_temp.pfspecific));
|
||||
continue;
|
||||
}
|
||||
if(PA_LOAD == pl_found->action) {
|
||||
META_DEBUG(1, ("ini: Plugin in line %d overrides loading of plugin with lower platform specific level %d, ours %d",
|
||||
ln, pl_found->pfspecific, pl_temp.pfspecific));
|
||||
//reset to empty
|
||||
reset_plugin(pl_found);
|
||||
}
|
||||
else {
|
||||
META_DEBUG(1, ("ini: Plugin in line %d should override existing plugin with lower platform specific level %d, ours %d. Unable to comply.",
|
||||
ln, pl_found->pfspecific, pl_temp.pfspecific));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// new plugin; add to list
|
||||
if((pl_added=add(&pl_temp))) {
|
||||
// try to load this plugin at the next opportunity
|
||||
pl_added->action=PA_LOAD;
|
||||
}
|
||||
else
|
||||
// error details logged in add()
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// This plugin is already in the current list of plugins.
|
||||
// Pathname already matches. Recopy desc, if specified in
|
||||
// plugins.ini.
|
||||
if(pl_temp.desc[0] != '<')
|
||||
STRNCPY(pl_found->desc, pl_temp.desc, sizeof(pl_found->desc));
|
||||
|
||||
// Check the file to see if it looks like it's been modified
|
||||
// since we last loaded it.
|
||||
if(!pl_found->newer_file()) {
|
||||
if(meta_errno==ME_NOFILE) {
|
||||
META_WARNING("ini: Skipping plugin, couldn't stat file '%s': %s",
|
||||
pl_found->pathname, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// File hasn't been updated.
|
||||
// Keep plugin (don't let refresh() unload it).
|
||||
pl_found->action=PA_KEEP;
|
||||
}
|
||||
}
|
||||
// Newer file on disk.
|
||||
else if(pl_found->status >= PL_OPENED) {
|
||||
META_DEBUG(2, ("ini: Plugin '%s' has newer file on disk", pl_found->desc));
|
||||
pl_found->action=PA_RELOAD;
|
||||
}
|
||||
else
|
||||
META_WARNING("ini: Plugin '%s' has newer file, but unexpected status (%s)",
|
||||
pl_found->desc, pl_found->str_status());
|
||||
}
|
||||
if(NULL != pl_found) {
|
||||
META_LOG("ini: Read plugin config for: %s", pl_found->desc);
|
||||
}
|
||||
else {
|
||||
META_LOG("ini: Read plugin config for: %s", pl_temp.desc);
|
||||
}
|
||||
n++;
|
||||
}
|
||||
META_LOG("ini: Finished reading plugins list: %s; Found %d plugins", inifile, n);
|
||||
|
||||
fclose(fp);
|
||||
if(!n) {
|
||||
META_WARNING("ini: Warning; no plugins found to load?");
|
||||
}
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
// Load a plugin from plugin request.
|
||||
// meta_errno values:
|
||||
// - errno's from resolve()
|
||||
// - ME_ALREADY this plugin already loaded
|
||||
// - errno's from add()
|
||||
// - errno's from load()
|
||||
MPlugin * DLLINTERNAL MPluginList::plugin_addload(plid_t plid, const char *fname, PLUG_LOADTIME now) {
|
||||
MPlugin pl_temp;
|
||||
MPlugin *pl_found, *pl_added, *pl_loader;
|
||||
|
||||
// Find loader plugin
|
||||
if(!(pl_loader=find(plid))) {
|
||||
// Couldn't find a matching file on disk
|
||||
META_DEBUG(1, ("Couldn't find plugin that gave this loading request!"));
|
||||
// meta_errno should be already set in resolve()
|
||||
RETURN_ERRNO(NULL, ME_BADREQ);
|
||||
}
|
||||
|
||||
memset(&pl_temp, 0, sizeof(pl_temp));
|
||||
|
||||
// copy filename
|
||||
if(!pl_temp.plugin_parseline(fname, pl_loader->index)) {
|
||||
// parse_plugin_load doesn't return mFALSE.
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
// resolve given path into a file; accepts various "shortcut"
|
||||
// pathnames.
|
||||
if(pl_temp.resolve() != mTRUE) {
|
||||
// Couldn't find a matching file on disk
|
||||
META_DEBUG(1, ("Couldn't resolve given path into a file: %s", pl_temp.file));
|
||||
// meta_errno should be already set in resolve()
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
// Try to find plugin with this pathname in the current list of
|
||||
// plugins.
|
||||
if((pl_found=find(pl_temp.pathname))) {
|
||||
// Already in list
|
||||
META_DEBUG(1, ("Plugin '%s' already in current list; file=%s desc='%s'",
|
||||
pl_temp.file, pl_found->file, pl_found->desc));
|
||||
RETURN_ERRNO(NULL, ME_ALREADY);
|
||||
}
|
||||
// new plugin; add to list
|
||||
if(!(pl_added=add(&pl_temp))) {
|
||||
META_DEBUG(1, ("Couldn't add plugin '%s' to list; see log", pl_temp.desc));
|
||||
// meta_errno should be already set in add()
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
// try to load new plugin (setting 'must load now')
|
||||
pl_added->action=PA_LOAD;
|
||||
if(!pl_added->load(now)) {
|
||||
// load failed
|
||||
if(meta_errno==ME_NOTALLOWED || meta_errno==ME_DELAYED) {
|
||||
META_DEBUG(1, ("Plugin '%s' couldn't attach; only allowed %s",
|
||||
pl_added->desc, pl_added->str_loadable(SL_ALLOWED)));
|
||||
pl_added->clear();
|
||||
}
|
||||
else if(pl_added->status == PL_OPENED)
|
||||
META_DEBUG(1, ("Opened plugin '%s', but failed to attach; see log", pl_added->desc));
|
||||
else
|
||||
META_DEBUG(1, ("Couldn't load plugin '%s'; see log", pl_added->desc));
|
||||
// meta_errno should be already set in load()
|
||||
return(NULL);
|
||||
}
|
||||
META_DEBUG(1, ("Loaded plugin '%s' successfully", pl_added->desc));
|
||||
meta_errno = ME_NOERROR;
|
||||
return(pl_added);
|
||||
}
|
||||
|
||||
// Load a plugin from a console command.
|
||||
// meta_errno values:
|
||||
// - errno's from cmd_parseline()
|
||||
// - errno's from resolve()
|
||||
// - ME_ALREADY this plugin already loaded
|
||||
// - errno's from add()
|
||||
// - errno's from load()
|
||||
mBOOL DLLINTERNAL MPluginList::cmd_addload(const char *args) {
|
||||
MPlugin pl_temp;
|
||||
MPlugin *pl_found, *pl_added;
|
||||
|
||||
memset(&pl_temp, 0, sizeof(pl_temp));
|
||||
|
||||
// XXX move back to comands_meta ?
|
||||
|
||||
// parse into a temp plugin
|
||||
if(pl_temp.cmd_parseline(args) != mTRUE) {
|
||||
META_CONS("Couldn't parse 'meta load' arguments: %s", args);
|
||||
// meta_errno should be already set in cmd_parseline()
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
// resolve given path into a file; accepts various "shortcut"
|
||||
// pathnames.
|
||||
if(pl_temp.resolve() != mTRUE) {
|
||||
// Couldn't find a matching file on disk
|
||||
META_CONS("Couldn't resolve given path into a file: %s",
|
||||
pl_temp.file);
|
||||
// meta_errno should be already set in resolve()
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
// Try to find plugin with this pathname in the current list of
|
||||
// plugins.
|
||||
if((pl_found=find(pl_temp.pathname))) {
|
||||
// Already in list
|
||||
META_CONS("Plugin '%s' already in current list; file=%s desc='%s'",
|
||||
pl_temp.file, pl_found->file, pl_found->desc);
|
||||
RETURN_ERRNO(mFALSE, ME_ALREADY);
|
||||
}
|
||||
// new plugin; add to list
|
||||
if(!(pl_added=add(&pl_temp))) {
|
||||
META_CONS("Couldn't add plugin '%s' to list; see log", pl_temp.desc);
|
||||
// meta_errno should be already set in add()
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
// try to load new plugin
|
||||
pl_added->action=PA_LOAD;
|
||||
if(!pl_added->load(PT_ANYTIME)) {
|
||||
// load failed
|
||||
if(meta_errno==ME_DELAYED)
|
||||
META_CONS("Loaded plugin '%s', but will wait to become active, %s",
|
||||
pl_added->desc, pl_added->str_loadable(SL_ALLOWED));
|
||||
else if(meta_errno==ME_NOTALLOWED) {
|
||||
META_CONS("Plugin '%s' couldn't attach; only allowed %s",
|
||||
pl_added->desc, pl_added->str_loadable(SL_ALLOWED));
|
||||
pl_added->clear();
|
||||
}
|
||||
else if(pl_added->status == PL_OPENED)
|
||||
META_CONS("Opened plugin '%s', but failed to attach; see log", pl_added->desc);
|
||||
else
|
||||
META_CONS("Couldn't load plugin '%s'; see log", pl_added->desc);
|
||||
show();
|
||||
// meta_errno should be already set in load()
|
||||
return(mFALSE);
|
||||
}
|
||||
META_CONS("Loaded plugin '%s' successfully", pl_added->desc);
|
||||
show();
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
// Load plugins at startup.
|
||||
// meta_errno values:
|
||||
// - errno's from ini_startup()
|
||||
mBOOL DLLINTERNAL MPluginList::load() {
|
||||
int i, n;
|
||||
|
||||
if(!ini_startup()) {
|
||||
META_WARNING("Problem loading plugins.ini: %s", inifile);
|
||||
// meta_errno should be already set in ini_startup()
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
META_LOG("dll: Loading plugins...");
|
||||
for(i=0, n=0; i < endlist; i++) {
|
||||
if(plist[i].status < PL_VALID)
|
||||
continue;
|
||||
if(plist[i].load(PT_STARTUP) == mTRUE)
|
||||
n++;
|
||||
else
|
||||
// all plugins should be loadable at startup...
|
||||
META_WARNING("dll: Failed to load plugin '%s'", plist[i].file);
|
||||
}
|
||||
META_LOG("dll: Finished loading %d plugins", n);
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
// Update list of loaded plugins from ini file, and load any new/changed plugins.
|
||||
// meta_errno values:
|
||||
// - errno's from ini_refresh()
|
||||
mBOOL DLLINTERNAL MPluginList::refresh(PLUG_LOADTIME now) {
|
||||
int i, ndone=0, nkept=0, nloaded=0, nunloaded=0, nreloaded=0, ndelayed=0;
|
||||
MPlugin *iplug;
|
||||
|
||||
if(!ini_refresh()) {
|
||||
META_WARNING("dll: Problem reloading plugins.ini: %s", inifile);
|
||||
// meta_errno should be already set in ini_refresh()
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
META_LOG("dll: Updating plugins...");
|
||||
for(i=0; i < endlist; i++) {
|
||||
iplug=&plist[i];
|
||||
if(iplug->status < PL_VALID)
|
||||
continue;
|
||||
switch(iplug->action) {
|
||||
case PA_KEEP:
|
||||
META_DEBUG(1, ("Keeping plugin '%s'", iplug->desc));
|
||||
iplug->action=PA_NONE;
|
||||
nkept++;
|
||||
break;
|
||||
case PA_LOAD:
|
||||
META_DEBUG(1, ("Loading plugin '%s'", iplug->desc));
|
||||
if(iplug->load(now))
|
||||
nloaded++;
|
||||
else if(meta_errno==ME_DELAYED)
|
||||
ndelayed++;
|
||||
break;
|
||||
case PA_RELOAD:
|
||||
META_DEBUG(1, ("Reloading plugin '%s'", iplug->desc));
|
||||
if(iplug->reload(now, PNL_FILE_NEWER))
|
||||
nreloaded++;
|
||||
else if(meta_errno==ME_DELAYED)
|
||||
ndelayed++;
|
||||
break;
|
||||
case PA_NONE:
|
||||
// If previously loaded from ini, but apparently removed from new ini.
|
||||
if(iplug->source==PS_INI && iplug->status >= PL_RUNNING) {
|
||||
META_DEBUG(1, ("Unloading plugin '%s'", iplug->desc));
|
||||
iplug->action=PA_UNLOAD;
|
||||
if(iplug->unload(now, PNL_INI_DELETED, PNL_INI_DELETED))
|
||||
nunloaded++;
|
||||
else if(meta_errno==ME_DELAYED)
|
||||
ndelayed++;
|
||||
}
|
||||
break;
|
||||
case PA_ATTACH:
|
||||
// Previously requested attach, but was delayed?
|
||||
META_DEBUG(1, ("Retrying attach plugin '%s'", iplug->desc));
|
||||
if(iplug->retry(now, PNL_DELAYED))
|
||||
nloaded++;
|
||||
else if(meta_errno==ME_DELAYED)
|
||||
ndelayed++;
|
||||
break;
|
||||
case PA_UNLOAD:
|
||||
// Previously requested unload, but was delayed?
|
||||
META_DEBUG(1, ("Retrying unload plugin '%s'", iplug->desc));
|
||||
if(iplug->retry(now, PNL_DELAYED))
|
||||
nunloaded++;
|
||||
else if(meta_errno==ME_DELAYED)
|
||||
ndelayed++;
|
||||
break;
|
||||
case PA_NULL:
|
||||
META_WARNING("dll: Unexpected action for plugin '%s': '%s'", iplug->desc, iplug->str_action());
|
||||
break;
|
||||
default:
|
||||
META_WARNING("dll: Unrecognized action for plugin '%s': '%s'", iplug->desc, iplug->str_action());
|
||||
break;
|
||||
}
|
||||
ndone++;
|
||||
}
|
||||
META_LOG("dll: Finished updating %d plugins; kept %d, loaded %d, unloaded %d, reloaded %d, delayed %d",
|
||||
ndone, nkept, nloaded, nunloaded, nreloaded, ndelayed);
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
// Re-enable any plugins currently paused.
|
||||
// meta_errno values:
|
||||
// - none
|
||||
void DLLINTERNAL MPluginList::unpause_all(void) {
|
||||
int i;
|
||||
MPlugin *iplug;
|
||||
for(i=0; i < endlist; i++) {
|
||||
iplug=&plist[i];
|
||||
if(iplug->status==PL_PAUSED)
|
||||
iplug->unpause();
|
||||
}
|
||||
}
|
||||
|
||||
// Retry any pending actions on plugins, for instance load/unload delayed
|
||||
// until changelevel.
|
||||
// meta_errno values:
|
||||
// - none
|
||||
void DLLINTERNAL MPluginList::retry_all(PLUG_LOADTIME now) {
|
||||
int i;
|
||||
MPlugin *iplug;
|
||||
for(i=0; i < endlist; i++) {
|
||||
iplug=&plist[i];
|
||||
if(iplug->action != PA_NONE)
|
||||
iplug->retry(now, PNL_DELAYED);
|
||||
}
|
||||
}
|
||||
|
||||
// List plugins and information about them in a formatted table.
|
||||
// meta_errno values:
|
||||
// - none
|
||||
void DLLINTERNAL MPluginList::show(int source_index) {
|
||||
int i, n=0, r=0;
|
||||
MPlugin *pl;
|
||||
char desc[15+1], file[16+1], vers[7+1]; // plus 1 for term null
|
||||
|
||||
if(source_index <= 0)
|
||||
META_CONS("Currently loaded plugins:");
|
||||
else
|
||||
META_CONS("Child plugins:");
|
||||
|
||||
META_CONS(" %*s %-*s %-4s %-4s %-*s v%-*s %-*s %-5s %-5s",
|
||||
WIDTH_MAX_PLUGINS, "",
|
||||
sizeof(desc)-1, "description",
|
||||
"stat", "pend",
|
||||
sizeof(file)-1, "file", sizeof(vers)-1, "ers",
|
||||
2+WIDTH_MAX_PLUGINS, "src",
|
||||
"load ", "unlod");
|
||||
|
||||
for(i=0; i < endlist; i++) {
|
||||
pl=&plist[i];
|
||||
if(pl->status < PL_VALID)
|
||||
continue;
|
||||
if(source_index > 0 && pl->source_plugin_index != source_index)
|
||||
continue;
|
||||
STRNCPY(desc, pl->desc, sizeof(desc));
|
||||
STRNCPY(file, pl->file, sizeof(file));
|
||||
if(pl->info && pl->info->version)
|
||||
STRNCPY(vers, pl->info->version, sizeof(vers));
|
||||
else
|
||||
STRNCPY(vers, " -", sizeof(vers));
|
||||
META_CONS(" [%*d] %-*s %-4s %-4s %-*s v%-*s %-*s %-5s %-5s",
|
||||
WIDTH_MAX_PLUGINS, pl->index,
|
||||
sizeof(desc)-1, desc,
|
||||
pl->str_status(ST_SHOW), pl->str_action(SA_SHOW),
|
||||
sizeof(file)-1, file, sizeof(vers)-1, vers,
|
||||
2+WIDTH_MAX_PLUGINS, pl->str_source(SO_SHOW),
|
||||
pl->str_loadable(SL_SHOW), pl->str_unloadable(SL_SHOW));
|
||||
if(pl->status == PL_RUNNING)
|
||||
r++;
|
||||
n++;
|
||||
}
|
||||
|
||||
META_CONS("%d plugins, %d running", n, r);
|
||||
}
|
||||
|
||||
// List plugins and information to Player/client entity. Differs from the
|
||||
// "meta list" console command in that:
|
||||
// - Shows only "running" plugins, skipping any failed or paused plugins.
|
||||
// - Limited info about each plugin, mostly the "public" info (name, author,
|
||||
// etc).
|
||||
// meta_errno values:
|
||||
// - none
|
||||
void DLLINTERNAL MPluginList::show_client(edict_t *pEntity) {
|
||||
int i, n=0;
|
||||
MPlugin *pl;
|
||||
META_CLIENT(pEntity, "Currently running plugins:");
|
||||
for(i=0; i < endlist; i++) {
|
||||
pl=&plist[i];
|
||||
if(pl->status != PL_RUNNING || !pl->info)
|
||||
continue;
|
||||
n++;
|
||||
META_CLIENT(pEntity, " [%3d] %s, v%s, %s, by %s, see %s",
|
||||
n,
|
||||
pl->info->name ? pl->info->name : "<unknown>",
|
||||
pl->info->version ? pl->info->version : "<?>",
|
||||
pl->info->date ? pl->info->date : "<../../..>",
|
||||
pl->info->author ? pl->info->author : "<unknown>",
|
||||
pl->info->url ? pl->info->url : "<unknown>");
|
||||
}
|
||||
META_CLIENT(pEntity, "%d plugins", n);
|
||||
}
|
||||
@@ -1,190 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// mplayer.cpp - methods of individual player (class MPlayer) and
|
||||
// list of players (class MPlayerList).
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h> // strdup()
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "mplayer.h" // me
|
||||
#include "sdk_util.h" // ENTINDEX()
|
||||
#include "metamod.h" // gpGlobals
|
||||
|
||||
|
||||
// Constructor
|
||||
MPlayer::MPlayer()
|
||||
: isQueried(mFALSE),
|
||||
cvarName(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// Destructor
|
||||
MPlayer::~MPlayer()
|
||||
{
|
||||
if(cvarName) {
|
||||
free(cvarName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Copy constructor
|
||||
MPlayer::MPlayer(const MPlayer& rhs)
|
||||
: isQueried(rhs.isQueried),
|
||||
cvarName(NULL)
|
||||
{
|
||||
if(rhs.cvarName) {
|
||||
cvarName = strdup(rhs.cvarName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Assignment operator
|
||||
MPlayer& DLLINTERNAL MPlayer::operator=(const MPlayer& rhs)
|
||||
{
|
||||
isQueried = rhs.isQueried;
|
||||
|
||||
if(cvarName) {
|
||||
free(cvarName);
|
||||
}
|
||||
|
||||
cvarName = NULL;
|
||||
|
||||
if(rhs.cvarName) {
|
||||
cvarName = strdup(rhs.cvarName);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// Mark a player as querying a client cvar and stores the cvar name
|
||||
// meta_errno values:
|
||||
// - ME_ARGUMENT cvar is NULL
|
||||
void DLLINTERNAL MPlayer::set_cvar_query(const char *cvar)
|
||||
{
|
||||
// Do not allow NULL as queried cvar since we use this as
|
||||
// return value in is_querying_cvar as indication if a
|
||||
// client cvar is queried.
|
||||
if(!cvar) {
|
||||
meta_errno = ME_ARGUMENT;
|
||||
return;
|
||||
}
|
||||
|
||||
isQueried = mTRUE;
|
||||
if(cvarName) {
|
||||
free(cvarName);
|
||||
}
|
||||
|
||||
cvarName = strdup(cvar);
|
||||
}
|
||||
|
||||
|
||||
// Unmark player as querying a client cvar
|
||||
void DLLINTERNAL MPlayer::clear_cvar_query(const char* /*cvar*/)
|
||||
{
|
||||
isQueried = mFALSE;
|
||||
if(cvarName) {
|
||||
free(cvarName);
|
||||
cvarName = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if a client cvar is queried for this player
|
||||
// Returns NULL if not
|
||||
// or the name of the cvar.
|
||||
const char * DLLINTERNAL MPlayer::is_querying_cvar(void)
|
||||
{
|
||||
if(isQueried) {
|
||||
return(cvarName);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Mark a player as querying a client cvar and stores the cvar name
|
||||
// meta_errno values:
|
||||
// - ME_ARGUMENT cvar is NULL
|
||||
void DLLINTERNAL MPlayerList::set_player_cvar_query(const edict_t *pEntity, const char *cvar)
|
||||
{
|
||||
int indx = ENTINDEX(const_cast<edict_t*>(pEntity));
|
||||
|
||||
if(indx < 1 || indx >= MPlayerList::NUM_SLOTS)
|
||||
return; //maybe output a message?
|
||||
|
||||
players[indx].set_cvar_query(cvar);
|
||||
}
|
||||
|
||||
|
||||
// Unmark player as querying a client cvar
|
||||
void DLLINTERNAL MPlayerList::clear_player_cvar_query(const edict_t *pEntity, const char *cvar)
|
||||
{
|
||||
int indx = ENTINDEX(const_cast<edict_t*>(pEntity));
|
||||
|
||||
if(indx < 1 || indx >= MPlayerList::NUM_SLOTS)
|
||||
return; //maybe output a message?
|
||||
|
||||
players[indx].clear_cvar_query(cvar);
|
||||
}
|
||||
|
||||
|
||||
void DLLINTERNAL MPlayerList::clear_all_cvar_queries(void)
|
||||
{
|
||||
for(int indx=1; indx < MPlayerList::NUM_SLOTS; ++indx) {
|
||||
players[indx].clear_cvar_query();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Check if a client cvar is queried for this player
|
||||
// Returns NULL if not
|
||||
// or the name of the cvar.
|
||||
// meta_errno values:
|
||||
// - ME_NOTFOUND invalid entity
|
||||
const char* DLLINTERNAL MPlayerList::is_querying_cvar(const edict_t *pEntity)
|
||||
{
|
||||
int indx = ENTINDEX(const_cast<edict_t*>(pEntity));
|
||||
|
||||
if(indx < 1 || indx > gpGlobals->maxClients) {
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
return(players[indx].is_querying_cvar());
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,532 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// mreg.cpp - functions for registered items (classes MRegCmd, MRegCmdList)
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef linux
|
||||
// enable extra routines in system header files, like strsignal
|
||||
# ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
# endif
|
||||
#endif /* linux */
|
||||
|
||||
#include <string.h> // strsignal, strdup, etc
|
||||
#include <errno.h> // strerror, etc
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "mreg.h" // me
|
||||
#include "metamod.h" // Plugins, etc
|
||||
#include "mlist.h" // class MPluginList
|
||||
#include "mplugin.h" // class MPlugin
|
||||
#include "types_meta.h" // mBOOL
|
||||
#include "log_meta.h" // META_LOG, etc
|
||||
#include "osdep.h" // os_safe_call, etc
|
||||
|
||||
|
||||
///// class MRegCmd:
|
||||
|
||||
// Init values. It would probably be more "proper" to use containers and
|
||||
// constructors, rather than arrays and init-functions.
|
||||
void DLLINTERNAL MRegCmd::init(int idx)
|
||||
{
|
||||
index = idx;
|
||||
name = NULL;
|
||||
pfnCmd = NULL;
|
||||
plugid = 0;
|
||||
status = RG_INVALID;
|
||||
}
|
||||
|
||||
// Try to call the function. Relies on OS-specific routine to attempt
|
||||
// calling the function without generating a segfault from an unloaded
|
||||
// plugin DLL.
|
||||
// meta_errno values:
|
||||
// - ME_BADREQ function disabled/invalid
|
||||
// - ME_ARGUMENT function pointer is null
|
||||
mBOOL DLLINTERNAL MRegCmd::call(void) {
|
||||
mBOOL ret;
|
||||
|
||||
// can we expect to call this function?
|
||||
if(status != RG_VALID)
|
||||
RETURN_ERRNO(mFALSE, ME_BADREQ);
|
||||
if(!pfnCmd)
|
||||
RETURN_ERRNO(mFALSE, ME_ARGUMENT);
|
||||
|
||||
// try to call this function
|
||||
ret=os_safe_call(pfnCmd);
|
||||
if(!ret) {
|
||||
META_DEBUG(4, ("Plugin reg_cmd '%s' called after unloaded; removed from list", name));
|
||||
status=RG_INVALID;
|
||||
pfnCmd=NULL;
|
||||
// NOTE: we can't free the malloc'd space for the name, as that
|
||||
// would just re-introduce the segfault problem..
|
||||
}
|
||||
// meta_errno (if failed) is set already in os_safe_call()
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
///// class MRegCmdList:
|
||||
|
||||
// Constructor
|
||||
MRegCmdList::MRegCmdList(void)
|
||||
: mlist(0), size(REG_CMD_GROWSIZE), endlist(0)
|
||||
{
|
||||
int i;
|
||||
mlist = (MRegCmd *) calloc(1, size * sizeof(MRegCmd));
|
||||
// initialize array
|
||||
for(i=0; i < size; i++)
|
||||
mlist[i].init(i+1); // 1-based index
|
||||
endlist=0;
|
||||
}
|
||||
|
||||
// Try to find a registered function with the given name.
|
||||
// meta_errno values:
|
||||
// - ME_NOTFOUND couldn't find a matching function
|
||||
MRegCmd * DLLINTERNAL MRegCmdList::find(const char *findname) {
|
||||
int i;
|
||||
for(i=0; i < endlist; i++) {
|
||||
if(!strcasecmp(mlist[i].name, findname))
|
||||
return(&mlist[i]);
|
||||
}
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
// Add the given name to the list and return the instance. This only
|
||||
// writes the "name" to the new cmd; other fields are writtin by caller
|
||||
// (meta_AddServerCommand).
|
||||
// meta_errno values:
|
||||
// - ME_NOMEM couldn't realloc or malloc for various parts
|
||||
MRegCmd * DLLINTERNAL MRegCmdList::add(const char *addname) {
|
||||
MRegCmd *icmd;
|
||||
|
||||
if(endlist==size) {
|
||||
// grow array
|
||||
MRegCmd *temp;
|
||||
int i, newsize;
|
||||
newsize=size+REG_CMD_GROWSIZE;
|
||||
META_DEBUG(6, ("Growing reg cmd list from %d to %d", size, newsize));
|
||||
temp = (MRegCmd *) realloc(mlist, newsize*sizeof(MRegCmd));
|
||||
if(!temp) {
|
||||
META_WARNING("Couldn't grow registered command list to %d for '%s': %s", newsize, addname, strerror(errno));
|
||||
RETURN_ERRNO(NULL, ME_NOMEM);
|
||||
}
|
||||
mlist=temp;
|
||||
size=newsize;
|
||||
// initialize new (unused) entries
|
||||
for(i=endlist; i<size; i++) {
|
||||
memset(&mlist[i], 0, sizeof(mlist[i]));
|
||||
mlist[i].init(i+1); // 1-based
|
||||
}
|
||||
}
|
||||
icmd = &mlist[endlist];
|
||||
|
||||
// Malloc space separately for the command name, because:
|
||||
// - Can't point to memory loc in plugin (another segv waiting to
|
||||
// happen).
|
||||
// - Can't point to memory in mlist which might get moved later by
|
||||
// realloc (again, segv).
|
||||
icmd->name=strdup(addname);
|
||||
if(!icmd->name) {
|
||||
META_WARNING("Couldn't strdup for adding reg cmd name '%s': %s",
|
||||
addname, strerror(errno));
|
||||
RETURN_ERRNO(NULL, ME_NOMEM);
|
||||
}
|
||||
endlist++;
|
||||
|
||||
return(icmd);
|
||||
}
|
||||
|
||||
// Disable any functions belonging to the given plugin (by index id).
|
||||
void DLLINTERNAL MRegCmdList::disable(int plugin_id) {
|
||||
int i;
|
||||
for(i=0; i < size; i++) {
|
||||
if(mlist[i].plugid == plugin_id)
|
||||
mlist[i].status = RG_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
// List all the registered commands.
|
||||
void DLLINTERNAL MRegCmdList::show(void) {
|
||||
int i, n=0, a=0;
|
||||
MRegCmd *icmd;
|
||||
MPlugin *iplug;
|
||||
char bplug[18+1]; // +1 for term null
|
||||
|
||||
META_CONS("Registered plugin commands:");
|
||||
META_CONS(" %*s %-*s %-s",
|
||||
WIDTH_MAX_REG, "",
|
||||
sizeof(bplug)-1, "plugin", "command");
|
||||
|
||||
for(i=0; i < endlist; i++) {
|
||||
icmd = &mlist[i];
|
||||
|
||||
if(icmd->status==RG_VALID) {
|
||||
iplug=Plugins->find(icmd->plugid);
|
||||
|
||||
if(iplug)
|
||||
STRNCPY(bplug, iplug->desc, sizeof(bplug));
|
||||
else
|
||||
STRNCPY(bplug, "(unknown)", sizeof(bplug));
|
||||
}
|
||||
else
|
||||
STRNCPY(bplug, "(unloaded)", sizeof(bplug));
|
||||
|
||||
META_CONS(" [%*d] %-*s %-s",
|
||||
WIDTH_MAX_REG, icmd->index,
|
||||
sizeof(bplug)-1, bplug,
|
||||
icmd->name);
|
||||
|
||||
if(icmd->status==RG_VALID)
|
||||
a++;
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
META_CONS("%d commands, %d available (%d allocated)", n, a, size);
|
||||
}
|
||||
|
||||
// List all the registered commands for the given plugin id.
|
||||
void DLLINTERNAL MRegCmdList::show(int plugin_id) {
|
||||
int i, n=0;
|
||||
MRegCmd *icmd;
|
||||
|
||||
/*
|
||||
// If OS doesn't support DLFNAME, then we can't know what the plugin's
|
||||
// registered cvars are.
|
||||
DLFNAME(NULL);
|
||||
if(meta_errno==ME_OSNOTSUP) {
|
||||
META_CONS("Registered commands: unknown (can't get info under this OS)");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
META_CONS("Registered commands:");
|
||||
for(i=0; i < endlist; i++) {
|
||||
icmd = &mlist[i];
|
||||
if(icmd->plugid != plugin_id)
|
||||
continue;
|
||||
META_CONS(" %s", icmd->name);
|
||||
n++;
|
||||
}
|
||||
META_CONS("%d commands", n);
|
||||
}
|
||||
|
||||
|
||||
///// class MRegCvar:
|
||||
|
||||
// Init values. It would probably be more "proper" to use containers and
|
||||
// constructors, rather than arrays and init-functions.
|
||||
void DLLINTERNAL MRegCvar::init(int idx)
|
||||
{
|
||||
index = idx;
|
||||
data = NULL;
|
||||
plugid = 0;
|
||||
status = RG_INVALID;
|
||||
}
|
||||
|
||||
// Set the cvar, copying values from given cvar.
|
||||
// meta_errno values:
|
||||
// - ME_ARGUMENT given cvar doesn't match this cvar
|
||||
mBOOL DLLINTERNAL MRegCvar::set(cvar_t *src) {
|
||||
if(strcasecmp(src->name, data->name)) {
|
||||
META_WARNING("Tried to set cvar with mismatched name; src=%s dst=%s",
|
||||
src->name, data->name);
|
||||
RETURN_ERRNO(mFALSE, ME_ARGUMENT);
|
||||
}
|
||||
// Would like to free() existing string, but can't tell where it was
|
||||
// allocated...
|
||||
data->string = strdup(src->string);
|
||||
data->flags = src->flags;
|
||||
data->value = src->value;
|
||||
data->next = src->next;
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
|
||||
///// class MRegCvarList:
|
||||
|
||||
// Constructor
|
||||
MRegCvarList::MRegCvarList(void)
|
||||
: vlist(0), size(REG_CVAR_GROWSIZE), endlist(0)
|
||||
{
|
||||
int i;
|
||||
vlist = (MRegCvar *) calloc(1, size * sizeof(MRegCvar));
|
||||
// initialize array
|
||||
for(i=0; i < size; i++)
|
||||
vlist[i].init(i+1); // 1-based
|
||||
endlist=0;
|
||||
}
|
||||
|
||||
// Add the given cvar name to the list and return the instance. This only
|
||||
// writes the "name" to the new cvar; other fields are written with
|
||||
// cvar::set().
|
||||
// meta_errno values:
|
||||
// - ME_NOMEM couldn't alloc or realloc for various parts
|
||||
MRegCvar * DLLINTERNAL MRegCvarList::add(const char *addname) {
|
||||
MRegCvar *icvar;
|
||||
|
||||
if(endlist==size) {
|
||||
// grow array
|
||||
MRegCvar *temp;
|
||||
int i, newsize;
|
||||
newsize=size+REG_CVAR_GROWSIZE;
|
||||
META_DEBUG(6, ("Growing reg cvar list from %d to %d", size, newsize));
|
||||
temp = (MRegCvar *) realloc(vlist, newsize*sizeof(MRegCvar));
|
||||
if(!temp) {
|
||||
META_WARNING("Couldn't grow registered cvar list to %d for '%s'; %s", newsize, addname, strerror(errno));
|
||||
RETURN_ERRNO(NULL, ME_NOMEM);
|
||||
}
|
||||
vlist=temp;
|
||||
size=newsize;
|
||||
// initialize new (unused) entries
|
||||
for(i=endlist; i<size; i++) {
|
||||
memset(&vlist[i], 0, sizeof(vlist[i]));
|
||||
vlist[i].init(i+1); // 1-based
|
||||
}
|
||||
}
|
||||
|
||||
icvar = &vlist[endlist];
|
||||
|
||||
// Malloc space for the cvar and cvar name, for two reasons:
|
||||
// - Can't point to memory loc in plugin (another segv waiting to
|
||||
// happen).
|
||||
// - Can't point to memory in vlist which might get moved later by
|
||||
// realloc (again, segv).
|
||||
icvar->data = (cvar_t *) calloc(1, sizeof(cvar_t));
|
||||
if(!icvar->data) {
|
||||
META_WARNING("Couldn't malloc cvar for adding reg cvar name '%s': %s",
|
||||
addname, strerror(errno));
|
||||
RETURN_ERRNO(NULL, ME_NOMEM);
|
||||
}
|
||||
icvar->data->name=strdup(addname);
|
||||
if(!icvar->data->name) {
|
||||
META_WARNING("Couldn't strdup for adding reg cvar name '%s': %s",
|
||||
addname, strerror(errno));
|
||||
RETURN_ERRNO(NULL, ME_NOMEM);
|
||||
}
|
||||
endlist++;
|
||||
|
||||
return(icvar);
|
||||
}
|
||||
|
||||
// Try to find a registered cvar with the given name.
|
||||
// meta_errno values:
|
||||
// - ME_NOTFOUND couldn't find a matching cvar
|
||||
MRegCvar * DLLINTERNAL MRegCvarList::find(const char *findname) {
|
||||
int i;
|
||||
for(i=0; i < endlist; i++) {
|
||||
if(!strcasecmp(vlist[i].data->name, findname))
|
||||
return(&vlist[i]);
|
||||
}
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
// Disable any cvars belonging to the given plugin (by index id).
|
||||
void DLLINTERNAL MRegCvarList::disable(int plugin_id) {
|
||||
int i;
|
||||
MRegCvar *icvar;
|
||||
for(i=0; i < size; i++) {
|
||||
icvar=&vlist[i];
|
||||
if(icvar->plugid == plugin_id) {
|
||||
icvar->status = RG_INVALID;
|
||||
icvar->plugid = 0;
|
||||
// Decided not to do this, in order to keep pre-existing values
|
||||
// after a plugin reload.
|
||||
// CVAR_SET_STRING(icvar->data->name, "[metamod: cvar invalid; plugin unloaded]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// List all the registered cvars.
|
||||
void DLLINTERNAL MRegCvarList::show(void) {
|
||||
int i, n=0, a=0;
|
||||
MRegCvar *icvar;
|
||||
MPlugin *iplug;
|
||||
char bplug[13+1], bname[20+1], bval[15+1]; // +1 for term null
|
||||
|
||||
META_CONS("Registered plugin cvars:");
|
||||
META_CONS(" %*s %-*s %-*s %*s %s",
|
||||
WIDTH_MAX_REG, "",
|
||||
sizeof(bplug)-1, "plugin",
|
||||
sizeof(bname)-1, "cvar",
|
||||
sizeof(bval)-1, "float value",
|
||||
"string value");
|
||||
|
||||
for(i=0; i < endlist; i++) {
|
||||
icvar = &vlist[i];
|
||||
if(icvar->status==RG_VALID) {
|
||||
iplug=Plugins->find(icvar->plugid);
|
||||
if(iplug)
|
||||
STRNCPY(bplug, iplug->desc, sizeof(bplug));
|
||||
else
|
||||
STRNCPY(bplug, "(unknown)", sizeof(bplug));
|
||||
}
|
||||
else
|
||||
STRNCPY(bplug, "(unloaded)", sizeof(bplug));
|
||||
STRNCPY(bname, icvar->data->name, sizeof(bname));
|
||||
safevoid_snprintf(bval, sizeof(bval), "%f", icvar->data->value);
|
||||
META_CONS(" [%*d] %-*s %-*s %*s %s",
|
||||
WIDTH_MAX_REG, icvar->index,
|
||||
sizeof(bplug)-1, bplug,
|
||||
sizeof(bname)-1, bname,
|
||||
sizeof(bval)-1, bval,
|
||||
icvar->data->string);
|
||||
if(icvar->status==RG_VALID)
|
||||
a++;
|
||||
n++;
|
||||
}
|
||||
META_CONS("%d cvars, %d available (%d allocated)", n, a, size);
|
||||
}
|
||||
|
||||
// List the registered cvars for the given plugin id.
|
||||
void DLLINTERNAL MRegCvarList::show(int plugin_id) {
|
||||
int i, n=0;
|
||||
MRegCvar *icvar;
|
||||
char bname[30+1], bval[15+1]; // +1 for term null
|
||||
|
||||
/*
|
||||
// If OS doesn't support DLFNAME, then we can't know what the plugin's
|
||||
// registered cvars are.
|
||||
DLFNAME(NULL);
|
||||
if(meta_errno==ME_OSNOTSUP) {
|
||||
META_CONS("Registered cvars: unknown (can't get info under this OS)");
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
META_CONS("%-*s %*s %s",
|
||||
sizeof(bname)-1, "Registered cvars:",
|
||||
sizeof(bval)-1, "float value",
|
||||
"string value");
|
||||
for(i=0; i < endlist; i++) {
|
||||
icvar = &vlist[i];
|
||||
if(icvar->plugid != plugin_id)
|
||||
continue;
|
||||
STRNCPY(bname, icvar->data->name, sizeof(bname));
|
||||
safevoid_snprintf(bval, sizeof(bval), "%f", icvar->data->value);
|
||||
META_CONS(" %-*s %*s %s",
|
||||
sizeof(bname)-1, bname,
|
||||
sizeof(bval)-1, bval,
|
||||
icvar->data->string);
|
||||
n++;
|
||||
}
|
||||
META_CONS("%d cvars", n);
|
||||
}
|
||||
|
||||
|
||||
///// class MRegMsgList:
|
||||
|
||||
// Constructor
|
||||
MRegMsgList::MRegMsgList(void)
|
||||
: size(MAX_REG_MSGS), endlist(0)
|
||||
{
|
||||
int i;
|
||||
// initialize array
|
||||
memset(mlist, 0, sizeof(mlist));
|
||||
for(i=0; i < size; i++) {
|
||||
mlist[i].index=i+1; // 1-based
|
||||
}
|
||||
endlist=0;
|
||||
}
|
||||
|
||||
// Add the given user msg the list and return the instance.
|
||||
// meta_errno values:
|
||||
// - ME_MAXREACHED reached max number of msgs allowed
|
||||
MRegMsg * DLLINTERNAL MRegMsgList::add(const char *addname, int addmsgid, int addsize) {
|
||||
MRegMsg *imsg;
|
||||
|
||||
if(endlist==size) {
|
||||
// all slots used
|
||||
META_ERROR("Couldn't add registered msg '%s' to list; reached max msgs (%d)",
|
||||
addname, size);
|
||||
RETURN_ERRNO(NULL, ME_MAXREACHED);
|
||||
}
|
||||
|
||||
imsg = &mlist[endlist];
|
||||
endlist++;
|
||||
|
||||
// Copy msg data into empty slot.
|
||||
// Note: 'addname' assumed to be a constant string allocated in the
|
||||
// gamedll.
|
||||
imsg->name=addname;
|
||||
imsg->msgid=addmsgid;
|
||||
imsg->size=addsize;
|
||||
|
||||
return(imsg);
|
||||
}
|
||||
|
||||
// Try to find a registered msg with the given name.
|
||||
// meta_errno values:
|
||||
// - ME_NOTFOUND couldn't find a matching cvar
|
||||
MRegMsg * DLLINTERNAL MRegMsgList::find(const char *findname) {
|
||||
int i;
|
||||
for(i=0; i < endlist; i++) {
|
||||
if(!mm_strcmp(mlist[i].name, findname))
|
||||
return(&mlist[i]);
|
||||
}
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
// Try to find a registered msg with the given msgid.
|
||||
// meta_errno values:
|
||||
// - ME_NOTFOUND couldn't find a matching cvar
|
||||
MRegMsg * DLLINTERNAL MRegMsgList::find(int findmsgid) {
|
||||
int i;
|
||||
for(i=0; i < endlist; i++) {
|
||||
if(mlist[i].msgid == findmsgid)
|
||||
return(&mlist[i]);
|
||||
}
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
|
||||
// List the registered usermsgs for the gamedll.
|
||||
void DLLINTERNAL MRegMsgList::show(void) {
|
||||
int i, n=0;
|
||||
MRegMsg *imsg;
|
||||
char bname[25+1]; // +1 for term null
|
||||
|
||||
META_CONS("%-*s %5s %5s",
|
||||
sizeof(bname)-1, "Game registered user msgs:", "msgid", "size");
|
||||
for(i=0; i < endlist; i++) {
|
||||
imsg = &mlist[i];
|
||||
STRNCPY(bname, imsg->name, sizeof(bname));
|
||||
META_CONS(" %-*s %3d %3d",
|
||||
sizeof(bname)-1, bname,
|
||||
imsg->msgid,
|
||||
imsg->size);
|
||||
n++;
|
||||
}
|
||||
META_CONS("%d game user msgs", n);
|
||||
}
|
||||
@@ -1,395 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// mutil.cpp - utility functions to provide to plugins
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h> // vsnprintf(), etc
|
||||
#include <stdarg.h> // vs_start(), etc
|
||||
#include <stdlib.h> // strtol()
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "meta_api.h" //
|
||||
#include "mutil.h" // me
|
||||
#include "mhook.h" // class MHookList, etc
|
||||
#include "linkent.h" // ENTITY_FN, etc
|
||||
#include "metamod.h" // Hooks, etc
|
||||
#include "types_meta.h" // mBOOL
|
||||
#include "osdep.h" // win32 vsnprintf, etc
|
||||
#include "sdk_util.h" // ALERT, etc
|
||||
|
||||
static hudtextparms_t default_csay_tparms = {
|
||||
-1, 0.25, // x, y
|
||||
2, // effect
|
||||
0, 255, 0, 0, // r, g, b, a1
|
||||
0, 0, 0, 0, // r2, g2, b2, a2
|
||||
0, 0, 10, 10, // fadein, fadeout, hold, fxtime
|
||||
1 // channel
|
||||
};
|
||||
|
||||
// Log to console; newline added.
|
||||
static void mutil_LogConsole(plid_t /* plid */, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char buf[MAX_LOGMSG_LEN];
|
||||
unsigned int len;
|
||||
|
||||
va_start(ap, fmt);
|
||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
// end msg with newline
|
||||
len=strlen(buf);
|
||||
if(len < sizeof(buf)-2) // -1 null, -1 for newline
|
||||
strcat(buf, "\n");
|
||||
else
|
||||
buf[len-1] = '\n';
|
||||
|
||||
SERVER_PRINT(buf);
|
||||
}
|
||||
|
||||
// Log regular message to logs; newline added.
|
||||
static void mutil_LogMessage(plid_t plid, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char buf[MAX_LOGMSG_LEN];
|
||||
plugin_info_t *plinfo;
|
||||
|
||||
plinfo=(plugin_info_t *)plid;
|
||||
va_start(ap, fmt);
|
||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
ALERT(at_logged, "[%s] %s\n", plinfo->logtag, buf);
|
||||
}
|
||||
|
||||
// Log an error message to logs; newline added.
|
||||
static void mutil_LogError(plid_t plid, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char buf[MAX_LOGMSG_LEN];
|
||||
plugin_info_t *plinfo;
|
||||
|
||||
plinfo=(plugin_info_t *)plid;
|
||||
va_start(ap, fmt);
|
||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
ALERT(at_logged, "[%s] ERROR: %s\n", plinfo->logtag, buf);
|
||||
}
|
||||
|
||||
// Log a message only if cvar "developer" set; newline added.
|
||||
static void mutil_LogDeveloper(plid_t plid, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
char buf[MAX_LOGMSG_LEN];
|
||||
plugin_info_t *plinfo;
|
||||
|
||||
if((int)CVAR_GET_FLOAT("developer") == 0)
|
||||
return;
|
||||
|
||||
plinfo=(plugin_info_t *)plid;
|
||||
va_start(ap, fmt);
|
||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
ALERT(at_logged, "[%s] dev: %s\n", plinfo->logtag, buf);
|
||||
}
|
||||
|
||||
// Print a center-message, with text parameters and varargs. Provides
|
||||
// functionality to the above center_say interfaces.
|
||||
static void mutil_CenterSayVarargs(plid_t plid, hudtextparms_t tparms,
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
char buf[MAX_LOGMSG_LEN];
|
||||
int n;
|
||||
edict_t *pEntity;
|
||||
|
||||
safevoid_vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
|
||||
mutil_LogMessage(plid, "(centersay) %s", buf);
|
||||
for(n=1; n <= gpGlobals->maxClients; n++) {
|
||||
pEntity=INDEXENT(n);
|
||||
META_UTIL_HudMessage(pEntity, tparms, buf);
|
||||
}
|
||||
}
|
||||
|
||||
// Print message on center of all player's screens. Uses default text
|
||||
// parameters (color green, 10 second fade-in).
|
||||
static void mutil_CenterSay(plid_t plid, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
mutil_CenterSayVarargs(plid, default_csay_tparms, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
// Print a center-message, with given text parameters.
|
||||
static void mutil_CenterSayParms(plid_t plid, hudtextparms_t tparms, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
mutil_CenterSayVarargs(plid, tparms, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
// Allow plugins to call the entity functions in the GameDLL. In
|
||||
// particular, calling "player()" as needed by most Bots. Suggested by
|
||||
// Jussi Kivilinna.
|
||||
static qboolean mutil_CallGameEntity(plid_t plid, const char *entStr, entvars_t *pev) {
|
||||
plugin_info_t *plinfo;
|
||||
ENTITY_FN pfnEntity;
|
||||
|
||||
plinfo=(plugin_info_t *)plid;
|
||||
META_DEBUG(8, ("Looking up game entity '%s' for plugin '%s'", entStr,
|
||||
plinfo->name));
|
||||
pfnEntity = (ENTITY_FN) DLSYM(GameDLL.handle, entStr);
|
||||
if(!pfnEntity) {
|
||||
META_WARNING("Couldn't find game entity '%s' in game DLL '%s' for plugin '%s'", entStr, GameDLL.name, plinfo->name);
|
||||
return(false);
|
||||
}
|
||||
META_DEBUG(7, ("Calling game entity '%s' for plugin '%s'", entStr,
|
||||
plinfo->name));
|
||||
(*pfnEntity)(pev);
|
||||
return(true);
|
||||
}
|
||||
|
||||
// Find a usermsg, registered by the gamedll, with the corresponding
|
||||
// msgname, and return remaining info about it (msgid, size).
|
||||
static int mutil_GetUserMsgID(plid_t plid, const char *msgname, int *size) {
|
||||
plugin_info_t *plinfo;
|
||||
MRegMsg *umsg;
|
||||
|
||||
plinfo=(plugin_info_t *)plid;
|
||||
META_DEBUG(8, ("Looking up usermsg name '%s' for plugin '%s'", msgname,
|
||||
plinfo->name));
|
||||
umsg=RegMsgs->find(msgname);
|
||||
if(umsg) {
|
||||
if(size)
|
||||
*size=umsg->size;
|
||||
return(umsg->msgid);
|
||||
}
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
// Find a usermsg, registered by the gamedll, with the corresponding
|
||||
// msgid, and return remaining info about it (msgname, size).
|
||||
static const char *mutil_GetUserMsgName(plid_t plid, int msgid, int *size) {
|
||||
plugin_info_t *plinfo;
|
||||
MRegMsg *umsg;
|
||||
|
||||
plinfo=(plugin_info_t *)plid;
|
||||
META_DEBUG(8, ("Looking up usermsg id '%d' for plugin '%s'", msgid,
|
||||
plinfo->name));
|
||||
// Guess names for any built-in Engine messages mentioned in the SDK;
|
||||
// from dlls/util.h.
|
||||
if(msgid < 64) {
|
||||
switch(msgid) {
|
||||
case SVC_TEMPENTITY:
|
||||
if(size) *size=-1;
|
||||
return("tempentity?");
|
||||
case SVC_INTERMISSION:
|
||||
if(size) *size=-1;
|
||||
return("intermission?");
|
||||
case SVC_CDTRACK:
|
||||
if(size) *size=-1;
|
||||
return("cdtrack?");
|
||||
case SVC_WEAPONANIM:
|
||||
if(size) *size=-1;
|
||||
return("weaponanim?");
|
||||
case SVC_ROOMTYPE:
|
||||
if(size) *size=-1;
|
||||
return("roomtype?");
|
||||
case SVC_DIRECTOR:
|
||||
if(size) *size=-1;
|
||||
return("director?");
|
||||
}
|
||||
}
|
||||
umsg=RegMsgs->find(msgid);
|
||||
if(umsg) {
|
||||
if(size)
|
||||
*size=umsg->size;
|
||||
// 'name' is assumed to be a constant string, allocated in the
|
||||
// gamedll.
|
||||
return(umsg->name);
|
||||
}
|
||||
else
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
// Return the full path of the plugin's loaded dll/so file.
|
||||
static const char *mutil_GetPluginPath(plid_t plid) {
|
||||
static char buf[PATH_MAX];
|
||||
MPlugin *plug;
|
||||
|
||||
plug=Plugins->find(plid);
|
||||
if(!plug) {
|
||||
META_WARNING("GetPluginPath: couldn't find plugin '%s'",
|
||||
plid->name);
|
||||
return(NULL);
|
||||
}
|
||||
STRNCPY(buf, plug->pathname, sizeof(buf));
|
||||
return(buf);
|
||||
}
|
||||
|
||||
// Return various string-based info about the game/MOD/gamedll.
|
||||
static const char *mutil_GetGameInfo(plid_t plid, ginfo_t type) {
|
||||
static char buf[MAX_STRBUF_LEN];
|
||||
const char *cp;
|
||||
switch(type) {
|
||||
case GINFO_NAME:
|
||||
cp=GameDLL.name;
|
||||
break;
|
||||
case GINFO_DESC:
|
||||
cp=GameDLL.desc;
|
||||
break;
|
||||
case GINFO_GAMEDIR:
|
||||
cp=GameDLL.gamedir;
|
||||
break;
|
||||
case GINFO_DLL_FULLPATH:
|
||||
cp=GameDLL.pathname;
|
||||
break;
|
||||
case GINFO_DLL_FILENAME:
|
||||
cp=GameDLL.file;
|
||||
break;
|
||||
case GINFO_REALDLL_FULLPATH:
|
||||
cp=GameDLL.real_pathname;
|
||||
break;
|
||||
default:
|
||||
META_WARNING("GetGameInfo: invalid request '%d' from plugin '%s'",
|
||||
type, plid->name);
|
||||
return(NULL);
|
||||
}
|
||||
STRNCPY(buf, cp, sizeof(buf));
|
||||
return(buf);
|
||||
}
|
||||
|
||||
static int mutil_LoadMetaPlugin(plid_t plid, const char *fname, PLUG_LOADTIME now, void **plugin_handle)
|
||||
{
|
||||
MPlugin *pl_loaded;
|
||||
|
||||
if(NULL == fname) {
|
||||
return(ME_ARGUMENT);
|
||||
}
|
||||
|
||||
meta_errno = ME_NOERROR;
|
||||
if(!(pl_loaded=Plugins->plugin_addload(plid, fname, now))) {
|
||||
if(plugin_handle)
|
||||
*plugin_handle = NULL;
|
||||
return(meta_errno);
|
||||
} else {
|
||||
if(plugin_handle)
|
||||
*plugin_handle = (void*)pl_loaded->handle;
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
static int mutil_UnloadMetaPlugin(plid_t plid, const char *fname, PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
|
||||
{
|
||||
MPlugin *findp = NULL;
|
||||
int pindex;
|
||||
char* endptr;
|
||||
|
||||
if(NULL == fname) {
|
||||
return(ME_ARGUMENT);
|
||||
}
|
||||
|
||||
pindex = strtol(fname, &endptr, 10);
|
||||
if(*fname != '\0' && *endptr == '\0')
|
||||
findp = Plugins->find(pindex);
|
||||
else
|
||||
findp = Plugins->find_match(fname);
|
||||
|
||||
if(!findp)
|
||||
return(meta_errno);
|
||||
|
||||
meta_errno = ME_NOERROR;
|
||||
|
||||
if(findp->plugin_unload(plid, now, reason))
|
||||
return(0);
|
||||
|
||||
return(meta_errno);
|
||||
}
|
||||
|
||||
static int mutil_UnloadMetaPluginByHandle(plid_t plid, void *plugin_handle, PLUG_LOADTIME now, PL_UNLOAD_REASON reason)
|
||||
{
|
||||
MPlugin *findp;
|
||||
|
||||
if(NULL == plugin_handle) {
|
||||
return(ME_ARGUMENT);
|
||||
}
|
||||
|
||||
if(!(findp=Plugins->find((DLHANDLE)plugin_handle)))
|
||||
return(ME_NOTFOUND);
|
||||
|
||||
meta_errno = ME_NOERROR;
|
||||
|
||||
if(findp->plugin_unload(plid, now, reason))
|
||||
return(0);
|
||||
|
||||
return(meta_errno);
|
||||
}
|
||||
|
||||
// Check if player is being queried for cvar
|
||||
static const char * mutil_IsQueryingClientCvar(plid_t /*plid*/, const edict_t *player) {
|
||||
return(g_Players.is_querying_cvar(player));
|
||||
}
|
||||
|
||||
//
|
||||
static int mutil_MakeRequestID(plid_t /*plid*/) {
|
||||
return(abs(0xbeef<<16) + (++requestid_counter));
|
||||
}
|
||||
|
||||
//
|
||||
static void mutil_GetHookTables(plid_t plid, enginefuncs_t **peng, DLL_FUNCTIONS **pdll, NEW_DLL_FUNCTIONS **pnewdll) {
|
||||
if (peng)
|
||||
*peng = &meta_engfuncs;
|
||||
if (pdll)
|
||||
*pdll = g_pHookedDllFunctions;
|
||||
if (pnewdll)
|
||||
*pnewdll = g_pHookedNewDllFunctions;
|
||||
}
|
||||
|
||||
// Meta Utility Function table.
|
||||
mutil_funcs_t MetaUtilFunctions = {
|
||||
mutil_LogConsole, // pfnLogConsole
|
||||
mutil_LogMessage, // pfnLogMessage
|
||||
mutil_LogError, // pfnLogError
|
||||
mutil_LogDeveloper, // pfnLogDeveloper
|
||||
mutil_CenterSay, // pfnCenterSay
|
||||
mutil_CenterSayParms, // pfnCenterSayParms
|
||||
mutil_CenterSayVarargs, // pfnCenterSayVarargs
|
||||
mutil_CallGameEntity, // pfnCallGameEntity
|
||||
mutil_GetUserMsgID, // pfnGetUserMsgID
|
||||
mutil_GetUserMsgName, // pfnGetUserMsgName
|
||||
mutil_GetPluginPath, // pfnGetPluginPath
|
||||
mutil_GetGameInfo, // pfnGetGameInfo
|
||||
mutil_LoadMetaPlugin, // pfnLoadPlugin
|
||||
mutil_UnloadMetaPlugin, // pfnUnloadPlugin
|
||||
mutil_UnloadMetaPluginByHandle, // pfnUnloadPluginByHandle
|
||||
mutil_IsQueryingClientCvar, // pfnIsQueryingClientCvar
|
||||
mutil_MakeRequestID, // pfnMakeRequestID
|
||||
mutil_GetHookTables, // pfnGetHookTables
|
||||
};
|
||||
@@ -1,399 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// osdep.cpp - routines for operating system differences
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef linux
|
||||
// enable extra routines in system header files, like dladdr
|
||||
# ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
# endif
|
||||
#include <dlfcn.h> // dlopen, dladdr, etc
|
||||
#endif /* linux */
|
||||
|
||||
#include <string.h> // strpbrk, etc
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "osdep.h" // me
|
||||
#include "mreg.h" // RG_VALID, etc
|
||||
#include "log_meta.h" // META_ERROR, etc
|
||||
#include "types_meta.h" // mBOOL
|
||||
#include "support_meta.h" // MAX_STRBUF_LEN
|
||||
#include "limits.h" // INT_MAX
|
||||
|
||||
|
||||
mBOOL dlclose_handle_invalid;
|
||||
|
||||
#ifdef _WIN32
|
||||
// Since windows doesn't provide a verison of strtok_r(), we include one
|
||||
// here. This may or may not operate exactly like strtok_r(), but does
|
||||
// what we need it it do.
|
||||
char * DLLINTERNAL my_strtok_r(char *s, const char *delim, char **ptrptr) {
|
||||
char *begin=NULL;
|
||||
char *end=NULL;
|
||||
char *rest=NULL;
|
||||
if(s)
|
||||
begin=s;
|
||||
else
|
||||
begin=*ptrptr;
|
||||
if(!begin)
|
||||
return(NULL);
|
||||
end=strpbrk(begin, delim);
|
||||
if(end) {
|
||||
*end='\0';
|
||||
rest=end+1;
|
||||
*ptrptr=rest+strspn(rest, delim);
|
||||
}
|
||||
else
|
||||
*ptrptr=NULL;
|
||||
return(begin);
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
||||
#ifdef linux
|
||||
char * DLLINTERNAL my_strlwr(char *s) {
|
||||
char *c;
|
||||
if(!s)
|
||||
return(0);
|
||||
for(c=s;*c;c++)
|
||||
*c = tolower(*c);
|
||||
return(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef DO_NOT_FIX_VARARG_ENGINE_API_WARPERS
|
||||
// Microsoft's msvcrt.dll:vsnprintf is buggy and so is vsnprintf on some glibc versions.
|
||||
// We use wrapper function to fix bugs.
|
||||
// from: http://sourceforge.net/tracker/index.php?func=detail&aid=1083721&group_id=2435&atid=102435
|
||||
int DLLINTERNAL safe_vsnprintf(char* s, size_t n, const char *format, va_list src_ap) {
|
||||
va_list ap;
|
||||
int res;
|
||||
char *tmpbuf;
|
||||
size_t bufsize = n;
|
||||
|
||||
if(s && n>0)
|
||||
s[0]=0;
|
||||
|
||||
// If the format string is empty, nothing to do.
|
||||
if(!format || !*format)
|
||||
return(0);
|
||||
|
||||
// The supplied count may be big enough. Try to use the library
|
||||
// vsnprintf, fixing up the case where the library function
|
||||
// neglects to terminate with '/0'.
|
||||
if(n > 0)
|
||||
{
|
||||
// A NULL destination will cause a segfault with vsnprintf.
|
||||
// if n > 0. Nor do we want to copy our tmpbuf to NULL later.
|
||||
if(!s)
|
||||
return(-1);
|
||||
|
||||
va_copy(ap, src_ap);
|
||||
res = vsnprintf(s, n, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if(res > 0) {
|
||||
if((unsigned)res == n)
|
||||
s[res - 1] = 0;
|
||||
return(res);
|
||||
}
|
||||
|
||||
// If n is already larger than INT_MAX, increasing it won't
|
||||
// help.
|
||||
if(n > INT_MAX)
|
||||
return(-1);
|
||||
|
||||
// Try a larger buffer.
|
||||
bufsize *= 2;
|
||||
}
|
||||
|
||||
if(bufsize < 1024)
|
||||
bufsize = 1024;
|
||||
|
||||
tmpbuf = (char *)malloc(bufsize * sizeof(char));
|
||||
if(!tmpbuf)
|
||||
return(-1);
|
||||
|
||||
va_copy(ap, src_ap);
|
||||
res = vsnprintf(tmpbuf, bufsize, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
// The test for bufsize limit is probably not necesary
|
||||
// with 2GB address space limit, since, in practice, malloc will
|
||||
// fail well before INT_MAX.
|
||||
while(res < 0 && bufsize <= INT_MAX) {
|
||||
char * newbuf;
|
||||
|
||||
bufsize *= 2;
|
||||
newbuf = (char*)realloc(tmpbuf, bufsize * sizeof(char));
|
||||
|
||||
if(!newbuf)
|
||||
break;
|
||||
|
||||
tmpbuf = newbuf;
|
||||
|
||||
va_copy(ap, src_ap);
|
||||
res = vsnprintf(tmpbuf, bufsize, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
if(res > 0 && n > 0) {
|
||||
if(n > (unsigned)res)
|
||||
memcpy(s, tmpbuf, (res + 1) * sizeof (char));
|
||||
else {
|
||||
memcpy(s, tmpbuf, (n - 1) * sizeof (char));
|
||||
s[n - 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
free(tmpbuf);
|
||||
return(res);
|
||||
}
|
||||
|
||||
int DLLINTERNAL safe_snprintf(char* s, size_t n, const char* format, ...) {
|
||||
int res;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
res = safe_vsnprintf(s, n, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
return(res);
|
||||
}
|
||||
#endif
|
||||
|
||||
void DLLINTERNAL safevoid_vsnprintf(char* s, size_t n, const char *format, va_list ap) {
|
||||
int res;
|
||||
|
||||
if(!s || n <= 0)
|
||||
return;
|
||||
|
||||
// If the format string is empty, nothing to do.
|
||||
if(!format || !*format) {
|
||||
s[0]=0;
|
||||
return;
|
||||
}
|
||||
|
||||
res = vsnprintf(s, n, format, ap);
|
||||
|
||||
// w32api returns -1 on too long write, glibc returns number of bytes it could have written if there were enough space
|
||||
// w32api doesn't write null at all, some buggy glibc don't either
|
||||
if(res < 0 || (size_t)res >= n)
|
||||
s[n-1]=0;
|
||||
}
|
||||
|
||||
void DLLINTERNAL safevoid_snprintf(char* s, size_t n, const char* format, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
safevoid_vsnprintf(s, n, format, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
// Windows doesn't provide a functon analagous to dlerr() that returns a
|
||||
// string describing the error, so we include one here, as exampled at:
|
||||
// http://msdn.microsoft.com/library/en-us/debug/errors_0sdh.asp
|
||||
// except without FORMAT_MESSAGE_ALLOCATE_BUFFER, since we use a local
|
||||
// static buffer.
|
||||
char * DLLINTERNAL str_GetLastError(void) {
|
||||
static char buf[MAX_STRBUF_LEN];
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //! Default language
|
||||
(LPTSTR) &buf, MAX_STRBUF_LEN-1, NULL);
|
||||
return(buf);
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
||||
// Find the filename of the DLL/shared-lib where the given memory location
|
||||
// exists.
|
||||
#ifdef linux
|
||||
// Errno values:
|
||||
// - ME_NOTFOUND couldn't find a sharedlib that contains memory location
|
||||
const char * DLLINTERNAL DLFNAME(void *memptr) {
|
||||
Dl_info dli;
|
||||
memset(&dli, 0, sizeof(dli));
|
||||
if(dladdr(memptr, &dli))
|
||||
return(dli.dli_fname);
|
||||
else
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
// Implementation for win32 provided by Jussi Kivilinna <kijuhe00@rhea.otol.fi>:
|
||||
//
|
||||
// 1. Get memory location info on memptr with VirtualQuery.
|
||||
// 2. Check if memory location info is valid and use MBI.AllocationBase
|
||||
// as module start point.
|
||||
// 3. Get module file name with GetModuleFileName.
|
||||
//
|
||||
// Simple and should work pretty much same way as 'dladdr' in linux.
|
||||
// VirtualQuery and GetModuleFileName work even with win32s.
|
||||
//
|
||||
// Note that GetModuleFileName returns longfilenames rather than 8.3.
|
||||
//
|
||||
// Note also, the returned filename is local static storage, and should be
|
||||
// copied by caller if it needs to keep it around.
|
||||
//
|
||||
// Also note, normalize_pathname() should really be done by the caller, but
|
||||
// is done here to preserve "const char *" return consistent with linux
|
||||
// version.
|
||||
//
|
||||
// Errno values:
|
||||
// - ME_NOTFOUND couldn't find a DLL that contains memory location
|
||||
const char * DLLINTERNAL DLFNAME(void *memptr) {
|
||||
MEMORY_BASIC_INFORMATION MBI;
|
||||
static char fname[PATH_MAX];
|
||||
|
||||
memset(fname, 0, sizeof(fname));
|
||||
|
||||
if(!VirtualQuery(memptr, &MBI, sizeof(MBI)))
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
if(MBI.State != MEM_COMMIT)
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
if(!MBI.AllocationBase)
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
|
||||
// MSDN indicates that GetModuleFileName will leave string
|
||||
// null-terminated, even if it's truncated because buffer is too small.
|
||||
if(!GetModuleFileNameA((HMODULE)MBI.AllocationBase, fname, sizeof(fname)-1))
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
if(!fname[0])
|
||||
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
||||
|
||||
normalize_pathname(fname);
|
||||
return(fname);
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
// Normalize/standardize a pathname.
|
||||
// - For win32, this involves:
|
||||
// - Turning backslashes (\) into slashes (/), so that config files and
|
||||
// Metamod internal code can be simpler and just use slashes (/).
|
||||
// - Turning upper/mixed case into lowercase, since windows is
|
||||
// non-case-sensitive.
|
||||
// - For linux, this requires no work, as paths uses slashes (/) natively,
|
||||
// and pathnames are case-sensitive.
|
||||
void DLLINTERNAL normalize_pathname(char *path) {
|
||||
char *cp;
|
||||
|
||||
META_DEBUG(8, ("normalize: %s", path));
|
||||
for(cp=path; *cp; cp++) {
|
||||
/*if(isupper(*cp))*/
|
||||
*cp=tolower(*cp);
|
||||
|
||||
if(*cp=='\\')
|
||||
*cp='/';
|
||||
}
|
||||
META_DEBUG(8, ("normalized: %s", path));
|
||||
}
|
||||
|
||||
// Buffer pointed to by resolved_name is assumed to be able to store a
|
||||
// string of PATH_MAX length.
|
||||
char * DLLINTERNAL realpath(const char *file_name, char *resolved_name) {
|
||||
int ret;
|
||||
ret=GetFullPathNameA(file_name, PATH_MAX, resolved_name, NULL);
|
||||
if(ret > PATH_MAX) {
|
||||
errno=ENAMETOOLONG;
|
||||
return(NULL);
|
||||
}
|
||||
else if(ret > 0) {
|
||||
HANDLE handle;
|
||||
WIN32_FIND_DATAA find_data;
|
||||
handle=FindFirstFileA(resolved_name, &find_data);
|
||||
if(INVALID_HANDLE_VALUE == handle) {
|
||||
errno=ENOENT;
|
||||
return(NULL);
|
||||
}
|
||||
FindClose(handle);
|
||||
normalize_pathname(resolved_name);
|
||||
return(resolved_name);
|
||||
}
|
||||
else
|
||||
return(NULL);
|
||||
}
|
||||
#endif /*_WIN32*/
|
||||
|
||||
|
||||
// Determine whether the given memory location is valid (ie whether we
|
||||
// should expect to be able to reference strings or functions at this
|
||||
// location without segfaulting).
|
||||
#ifdef linux
|
||||
// Simulate this with dladdr. I'm not convinced this will be as generally
|
||||
// applicable as the native windows routine below, but it should do what
|
||||
// we need it for in this particular situation.
|
||||
// meta_errno values:
|
||||
// - ME_NOTFOUND couldn't find a matching sharedlib for this ptr
|
||||
mBOOL DLLINTERNAL IS_VALID_PTR(void *memptr) {
|
||||
Dl_info dli;
|
||||
memset(&dli, 0, sizeof(dli));
|
||||
if(dladdr(memptr, &dli))
|
||||
return(mTRUE);
|
||||
else
|
||||
RETURN_ERRNO(mFALSE, ME_NOTFOUND);
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
// Use the native windows routine IsBadCodePtr.
|
||||
// meta_errno values:
|
||||
// - ME_BADMEMPTR not a valid memory pointer
|
||||
mBOOL DLLINTERNAL IS_VALID_PTR(void *memptr) {
|
||||
if(IsBadCodePtr((FARPROC) memptr))
|
||||
RETURN_ERRNO(mFALSE, ME_BADMEMPTR);
|
||||
else
|
||||
return(mTRUE);
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
// This used to be OS-dependent, as it used a SEGV signal handler under
|
||||
// linux, but that was removed because (a) it masked legitimate segfaults
|
||||
// in plugin commands and produced confusing output ("plugin has been
|
||||
// unloaded", when really it segfaultd), and (b) wasn't necessary since
|
||||
// IS_VALID_PTR() should cover the situation.
|
||||
mBOOL DLLINTERNAL os_safe_call(REG_CMD_FN pfn) {
|
||||
// try and see if this is a valid memory location
|
||||
if(!IS_VALID_PTR((void *) pfn))
|
||||
// meta_errno should be already set in is_valid_ptr()
|
||||
return(mFALSE);
|
||||
|
||||
pfn();
|
||||
return(mTRUE);
|
||||
}
|
||||
|
||||
@@ -1,341 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
||||
*
|
||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
// enable extra routines in system header files, like dladdr
|
||||
# ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
# endif
|
||||
#include <dlfcn.h> // dlopen, dladdr, etc
|
||||
#include <signal.h> // sigaction, etc
|
||||
#include <setjmp.h> // sigsetjmp, longjmp, etc
|
||||
#include <sys/mman.h> // mmap, munmap, mprotect, etc
|
||||
#include <link.h>
|
||||
#include <elf.h>
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "osdep_p.h" // me
|
||||
#include "support_meta.h" // STRNCPY
|
||||
|
||||
|
||||
// On linux manually search for exports from dynamic library file.
|
||||
// --Jussi Kivilinna
|
||||
static jmp_buf signal_jmp_buf;
|
||||
|
||||
// Signal handler for is_gamedll()
|
||||
static void signal_handler_sigsegv(int) {
|
||||
/*
|
||||
* GLIBC 2.11+ intercept longjmp with __longjmp_chk. However we want
|
||||
* binary compability with older versions of GLIBC.
|
||||
*/
|
||||
#ifdef __amd64__
|
||||
__asm__ volatile(".symver __longjmp_chk,longjmp@GLIBC_2.2.5"
|
||||
:
|
||||
:"r"(&signal_jmp_buf)
|
||||
:"memory");
|
||||
#else
|
||||
__asm__ volatile(".symver __longjmp_chk,longjmp@GLIBC_2.0"
|
||||
:
|
||||
:"r"(&signal_jmp_buf)
|
||||
:"memory");
|
||||
#endif /*__amd64__*/
|
||||
longjmp(signal_jmp_buf, 1);
|
||||
}
|
||||
|
||||
#define invalid_elf_ptr(x) (((unsigned long)&(x)) > file_end - 1)
|
||||
#define invalid_elf_offset(x) (((unsigned long)(x)) > filesize - 1)
|
||||
#define elf_error_exit() \
|
||||
do { \
|
||||
sigaction(SIGSEGV, &oldaction, 0); \
|
||||
META_DEBUG(3, ("is_gamedll(%s): Invalid ELF.", filename)); \
|
||||
munmap(ehdr, filesize); \
|
||||
return(mFALSE); \
|
||||
} while(0)
|
||||
|
||||
mBOOL DLLINTERNAL is_gamedll(const char *filename) {
|
||||
// When these are not static there are some mysterious hidden bugs that I can't find/solve.
|
||||
// So this is simple workaround.
|
||||
static struct sigaction action;
|
||||
static struct sigaction oldaction;
|
||||
static ElfW(Ehdr) * ehdr = 0;
|
||||
static ElfW(Shdr) * shdr = 0;
|
||||
static ElfW(Sym) * symtab = 0;
|
||||
static char * strtab = 0;
|
||||
static FILE * pf = 0;
|
||||
static unsigned long filesize = 0;
|
||||
static unsigned long strtab_size = 0;
|
||||
static unsigned long nsyms = 0;
|
||||
static unsigned long i = 0;
|
||||
static unsigned long file_end = 0;
|
||||
static char * funcname = 0;
|
||||
static int has_GiveFnptrsToDll = 0;
|
||||
static int has_GetEntityAPI2 = 0;
|
||||
static int has_GetEntityAPI = 0;
|
||||
|
||||
ehdr = 0;
|
||||
shdr = 0;
|
||||
symtab = 0;
|
||||
strtab = 0;
|
||||
pf = 0;
|
||||
filesize = 0;
|
||||
file_end = 0;
|
||||
strtab_size = 0;
|
||||
nsyms = 0;
|
||||
i = 0;
|
||||
funcname = 0;
|
||||
has_GiveFnptrsToDll = 0;
|
||||
has_GetEntityAPI2 = 0;
|
||||
has_GetEntityAPI = 0;
|
||||
|
||||
// Try open file and get filesize
|
||||
if((pf = fopen(filename, "rb"))) {
|
||||
fseek(pf, 0, SEEK_END);
|
||||
filesize = ftell(pf);
|
||||
fseek(pf, 0, SEEK_SET);
|
||||
} else {
|
||||
META_DEBUG(3, ("is_gamedll(%s): Failed, cannot fopen() file.", filename));
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
// Check that filesize is atleast size of ELF header!
|
||||
if(filesize < sizeof(ElfW(Ehdr))) {
|
||||
#ifdef __x86_64__
|
||||
META_DEBUG(3, ("is_gamedll(%s): Failed, file is too small to be ELF64. [%i < %i]", filename, filesize, sizeof(ElfW(Ehdr))));
|
||||
#else
|
||||
META_DEBUG(3, ("is_gamedll(%s): Failed, file is too small to be ELF32. [%i < %i]", filename, filesize, sizeof(ElfW(Ehdr))));
|
||||
#endif
|
||||
fclose(pf);
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
// mmap library for easy reading
|
||||
ehdr = (ElfW(Ehdr) *)mmap(0, filesize, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(pf), 0);
|
||||
file_end = (unsigned long)ehdr + filesize;
|
||||
|
||||
// not needed anymore
|
||||
fclose(pf);
|
||||
|
||||
// check if mmap was successful
|
||||
if(!ehdr || (void*)ehdr==(void*)-1) {
|
||||
META_DEBUG(3, ("is_gamedll(%s): Failed, mmap() [0x%x]", filename, ehdr));
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
//In case that ELF file is incomplete (because bad upload etc), we protect memory-mapping access with signal-handler
|
||||
if(!setjmp(signal_jmp_buf)) {
|
||||
memset(&action, 0, sizeof(struct sigaction));
|
||||
memset(&oldaction, 0, sizeof(struct sigaction));
|
||||
|
||||
// Not returning from signal, set SIGSEGV handler.
|
||||
action.sa_handler = signal_handler_sigsegv;
|
||||
action.sa_flags = SA_RESETHAND | SA_NODEFER;
|
||||
sigemptyset(&action.sa_mask);
|
||||
sigaction(SIGSEGV, &action, &oldaction);
|
||||
} else {
|
||||
// Reset signal handler.
|
||||
sigaction(SIGSEGV, &oldaction, 0);
|
||||
|
||||
META_DEBUG(3, ("is_gamedll(%s): Failed, signal SIGSEGV.", filename));
|
||||
|
||||
munmap(ehdr, filesize);
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
if(mm_strncmp((char *)ehdr, ELFMAG, SELFMAG) != 0 || ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
|
||||
// Reset signal handler.
|
||||
sigaction(SIGSEGV, &oldaction, 0);
|
||||
|
||||
META_DEBUG(3, ("is_gamedll(%s): Failed, file isn't ELF (%02x%02x%02x%02x:%x).", filename,
|
||||
((char *)ehdr)[0], ((char *)ehdr)[1], ((char *)ehdr)[2], ((char *)ehdr)[3], ehdr->e_ident[EI_VERSION]));
|
||||
|
||||
munmap(ehdr, filesize);
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
// check if x86_64-shared-library
|
||||
if(ehdr->e_ident[EI_CLASS] != ELFCLASS64 || ehdr->e_type != ET_DYN || ehdr->e_machine != EM_X86_64) {
|
||||
// Reset signal handler.
|
||||
sigaction(SIGSEGV, &oldaction, 0);
|
||||
|
||||
META_DEBUG(3, ("is_gamedll(%s): Failed, ELF isn't for target:x86_64. [%x:%x:%x]", filename,
|
||||
ehdr->e_ident[EI_CLASS], ehdr->e_type, ehdr->e_machine));
|
||||
|
||||
munmap(ehdr, filesize);
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
#else
|
||||
// check if x86-shared-library
|
||||
if(ehdr->e_ident[EI_CLASS] != ELFCLASS32 || ehdr->e_type != ET_DYN || ehdr->e_machine != EM_386) {
|
||||
// Reset signal handler.
|
||||
sigaction(SIGSEGV, &oldaction, 0);
|
||||
|
||||
META_DEBUG(3, ("is_gamedll(%s): Failed, ELF isn't for target:i386. [%x:%x:%x]", filename,
|
||||
ehdr->e_ident[EI_CLASS], ehdr->e_type, ehdr->e_machine));
|
||||
|
||||
munmap(ehdr, filesize);
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
//Get symtab and strtab info
|
||||
shdr = (ElfW(Shdr) *)((char *)ehdr + ehdr->e_shoff);
|
||||
if(invalid_elf_ptr(shdr[ehdr->e_shnum]))
|
||||
elf_error_exit();
|
||||
|
||||
for(i = 0; i < ehdr->e_shnum; i++) {
|
||||
// searching for dynamic linker symbol table
|
||||
if(shdr[i].sh_type == SHT_DYNSYM) {
|
||||
if(invalid_elf_offset(shdr[i].sh_offset) ||
|
||||
invalid_elf_ptr(shdr[shdr[i].sh_link]) ||
|
||||
invalid_elf_offset(shdr[shdr[i].sh_link].sh_offset) ||
|
||||
invalid_elf_ptr(strtab[strtab_size]) ||
|
||||
invalid_elf_ptr(symtab[nsyms]))
|
||||
elf_error_exit();
|
||||
|
||||
symtab = (ElfW(Sym) *)((char *)ehdr + shdr[i].sh_offset);
|
||||
strtab = (char *)((char *)ehdr + shdr[shdr[i].sh_link].sh_offset);
|
||||
strtab_size = shdr[shdr[i].sh_link].sh_size;
|
||||
nsyms = shdr[i].sh_size / shdr[i].sh_entsize;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!symtab) {
|
||||
//Another method for finding symtab
|
||||
for(i = 0; i < ehdr->e_shnum; i++) {
|
||||
if(shdr[i].sh_type == SHT_SYMTAB) {
|
||||
if(invalid_elf_offset(shdr[i].sh_offset) ||
|
||||
invalid_elf_ptr(shdr[shdr[i].sh_link]) ||
|
||||
invalid_elf_offset(shdr[shdr[i].sh_link].sh_offset) ||
|
||||
invalid_elf_ptr(strtab[strtab_size]) ||
|
||||
invalid_elf_ptr(symtab[nsyms]))
|
||||
elf_error_exit();
|
||||
|
||||
symtab = (ElfW(Sym) *)((char *)ehdr + shdr[i].sh_offset);
|
||||
strtab = (char *)((char *)ehdr + shdr[shdr[i].sh_link].sh_offset);
|
||||
strtab_size = shdr[shdr[i].sh_link].sh_size;
|
||||
nsyms = shdr[i].sh_size / shdr[i].sh_entsize;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!symtab) {
|
||||
// Reset signal handler.
|
||||
sigaction(SIGSEGV, &oldaction, 0);
|
||||
|
||||
META_DEBUG(3, ("is_gamedll(%s): Failed, couldn't locate symtab.", filename));
|
||||
|
||||
munmap(ehdr, filesize);
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
//Search symbols for exports
|
||||
for(i = 0; i < nsyms; i++) {
|
||||
#ifdef __x86_64__
|
||||
// Export?
|
||||
if(ELF64_ST_TYPE(symtab[i].st_info) != STT_FUNC || ELF64_ST_BIND(symtab[i].st_info) != STB_GLOBAL)
|
||||
continue;
|
||||
#else
|
||||
// Export?
|
||||
if(ELF32_ST_TYPE(symtab[i].st_info) != STT_FUNC || ELF32_ST_BIND(symtab[i].st_info) != STB_GLOBAL)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
// string outside strtab?
|
||||
if(symtab[i].st_name <= 0 || symtab[i].st_name >= strtab_size)
|
||||
continue;
|
||||
|
||||
funcname = &strtab[symtab[i].st_name];
|
||||
|
||||
// Check
|
||||
// Fast check for 'G' first
|
||||
if(funcname[0] == 'G') {
|
||||
// Collect export information
|
||||
if(!has_GiveFnptrsToDll)
|
||||
has_GiveFnptrsToDll = strmatch(funcname, "GiveFnptrsToDll");
|
||||
if(!has_GetEntityAPI2)
|
||||
has_GetEntityAPI2 = strmatch(funcname, "GetEntityAPI2");
|
||||
if(!has_GetEntityAPI)
|
||||
has_GetEntityAPI = strmatch(funcname, "GetEntityAPI");
|
||||
}
|
||||
// Check if metamod plugin
|
||||
else if(funcname[0] == 'M') {
|
||||
if(strmatch(funcname, "Meta_Init") ||
|
||||
strmatch(funcname, "Meta_Query") ||
|
||||
strmatch(funcname, "Meta_Attach") ||
|
||||
strmatch(funcname, "Meta_Detach")) {
|
||||
// Metamod plugin.. is not gamedll
|
||||
META_DEBUG(5, ("is_gamedll(%s): Detected Metamod plugin, library exports [%s].", filename, funcname));
|
||||
|
||||
// Reset signal handler.
|
||||
sigaction(SIGSEGV, &oldaction, 0);
|
||||
|
||||
munmap(ehdr, filesize);
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if gamedll
|
||||
if(has_GiveFnptrsToDll && (has_GetEntityAPI2 || has_GetEntityAPI)) {
|
||||
// This is gamedll!
|
||||
META_DEBUG(5, ("is_gamedll(%s): Detected GameDLL.", filename));
|
||||
|
||||
// Reset signal handler.
|
||||
sigaction(SIGSEGV, &oldaction, 0);
|
||||
|
||||
munmap(ehdr, filesize);
|
||||
|
||||
return(mTRUE);
|
||||
} else {
|
||||
META_DEBUG(5, ("is_gamedll(%s): Library isn't GameDLL.", filename));
|
||||
}
|
||||
|
||||
// Reset signal handler.
|
||||
sigaction(SIGSEGV, &oldaction, 0);
|
||||
|
||||
munmap(ehdr, filesize);
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
||||
*
|
||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "osdep_p.h" // me
|
||||
#include "support_meta.h" // STRNCPY
|
||||
|
||||
//check for invalid handle values
|
||||
#define is_invalid_handle(X) ((X)==0 || (X)==INVALID_HANDLE_VALUE)
|
||||
|
||||
//relative virtual address to virtual address
|
||||
#define rva_to_va(base, rva) ((unsigned long)base + (unsigned long)rva)
|
||||
//virtual address to relative virtual address
|
||||
#define va_to_rva(base, va) ((unsigned long)va - (unsigned long)base)
|
||||
|
||||
//
|
||||
static unsigned long DLLINTERNAL_NOVIS va_to_mapaddr(void * mapview, IMAGE_SECTION_HEADER * sections, int num_sects, unsigned long vaddr) {
|
||||
for(int i = 0; i < num_sects; i++)
|
||||
if(vaddr >= sections[i].VirtualAddress && vaddr < sections[i].VirtualAddress + sections[i].SizeOfRawData)
|
||||
return(rva_to_va(mapview, (vaddr - sections[i].VirtualAddress + sections[i].PointerToRawData)));
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
// Checks module signatures and return ntheaders pointer for valid module
|
||||
static IMAGE_NT_HEADERS * DLLINTERNAL_NOVIS get_ntheaders(void * mapview) {
|
||||
union {
|
||||
unsigned long mem;
|
||||
IMAGE_DOS_HEADER * dos;
|
||||
IMAGE_NT_HEADERS * pe;
|
||||
} mem;
|
||||
|
||||
//Check if valid dos header
|
||||
mem.mem = (unsigned long)mapview;
|
||||
if(IsBadReadPtr(mem.dos, sizeof(*mem.dos)) || mem.dos->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return(0);
|
||||
|
||||
//Get and check pe header
|
||||
mem.mem = rva_to_va(mapview, mem.dos->e_lfanew);
|
||||
if(IsBadReadPtr(mem.pe, sizeof(*mem.pe)) || mem.pe->Signature != IMAGE_NT_SIGNATURE)
|
||||
return(0);
|
||||
|
||||
return(mem.pe);
|
||||
}
|
||||
|
||||
// Returns export table for valid module
|
||||
static IMAGE_EXPORT_DIRECTORY * DLLINTERNAL_NOVIS get_export_table(void * mapview, IMAGE_NT_HEADERS * ntheaders, IMAGE_SECTION_HEADER * sections, int num_sects) {
|
||||
union {
|
||||
unsigned long mem;
|
||||
void * pvoid;
|
||||
IMAGE_DOS_HEADER * dos;
|
||||
IMAGE_NT_HEADERS * pe;
|
||||
IMAGE_EXPORT_DIRECTORY * export_dir;
|
||||
} mem;
|
||||
|
||||
mem.pe = ntheaders;
|
||||
|
||||
//Check for exports
|
||||
if(!mem.pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
|
||||
return(0);
|
||||
|
||||
mem.mem = va_to_mapaddr(mapview, sections, num_sects, mem.pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
if(IsBadReadPtr(mem.export_dir, sizeof(*mem.export_dir)))
|
||||
return(0);
|
||||
|
||||
return(mem.export_dir);
|
||||
}
|
||||
|
||||
mBOOL DLLINTERNAL is_gamedll(const char *filename) {
|
||||
HANDLE hFile;
|
||||
HANDLE hMap;
|
||||
void * mapview;
|
||||
IMAGE_NT_HEADERS * ntheaders;
|
||||
IMAGE_SECTION_HEADER * sections;
|
||||
int num_sects;
|
||||
IMAGE_EXPORT_DIRECTORY * exports;
|
||||
|
||||
int has_GiveFnptrsToDll = 0;
|
||||
int has_GetEntityAPI2 = 0;
|
||||
int has_GetEntityAPI = 0;
|
||||
|
||||
// Try open file for read
|
||||
hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(is_invalid_handle(hFile)) {
|
||||
META_DEBUG(3, ("is_gamedll(%s): CreateFile() failed.", filename));
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
//
|
||||
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
if(is_invalid_handle(hMap)) {
|
||||
META_DEBUG(3, ("is_gamedll(%s): CreateFileMapping() failed.", filename));
|
||||
CloseHandle(hFile);
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
//
|
||||
mapview = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
||||
if(!mapview) {
|
||||
META_DEBUG(3, ("is_gamedll(%s): MapViewOfFile() failed.", filename));
|
||||
CloseHandle(hMap);
|
||||
CloseHandle(hFile);
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
ntheaders = get_ntheaders(mapview);
|
||||
if(!ntheaders) {
|
||||
META_DEBUG(3, ("is_gamedll(%s): get_ntheaders() failed.", filename));
|
||||
UnmapViewOfFile(mapview);
|
||||
CloseHandle(hMap);
|
||||
CloseHandle(hFile);
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
//Sections for va_to_mapaddr function
|
||||
sections = IMAGE_FIRST_SECTION(ntheaders);
|
||||
num_sects = ntheaders->FileHeader.NumberOfSections;
|
||||
if(IsBadReadPtr(sections, num_sects * sizeof(IMAGE_SECTION_HEADER))) {
|
||||
META_DEBUG(3, ("is_gamedll(%s): IMAGE_FIRST_SECTION() failed.", filename));
|
||||
UnmapViewOfFile(mapview);
|
||||
CloseHandle(hMap);
|
||||
CloseHandle(hFile);
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
//
|
||||
exports = get_export_table(mapview, ntheaders, sections, num_sects);
|
||||
if(!exports) {
|
||||
META_DEBUG(3, ("is_gamedll(%s): get_export_table() failed.", filename));
|
||||
UnmapViewOfFile(mapview);
|
||||
CloseHandle(hMap);
|
||||
CloseHandle(hFile);
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
//
|
||||
unsigned long * names = (unsigned long *)va_to_mapaddr(mapview, sections, num_sects, exports->AddressOfNames);
|
||||
if(IsBadReadPtr(names, exports->NumberOfNames * sizeof(unsigned long))) {
|
||||
META_DEBUG(3, ("is_gamedll(%s): Pointer to exported function names is invalid.", filename));
|
||||
UnmapViewOfFile(mapview);
|
||||
CloseHandle(hMap);
|
||||
CloseHandle(hFile);
|
||||
return(mFALSE);
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < exports->NumberOfNames; i++) {
|
||||
//get function name with valid address
|
||||
char * funcname = (char *)va_to_mapaddr(mapview, sections, num_sects, names[i]);
|
||||
if(IsBadStringPtrA(funcname, 128))
|
||||
continue;
|
||||
|
||||
// Check
|
||||
// Fast check for 'G' first
|
||||
if(funcname[0] == 'G') {
|
||||
// Collect export information
|
||||
if(!has_GiveFnptrsToDll)
|
||||
has_GiveFnptrsToDll = strmatch(funcname, "GiveFnptrsToDll");
|
||||
if(!has_GetEntityAPI2)
|
||||
has_GetEntityAPI2 = strmatch(funcname, "GetEntityAPI2");
|
||||
if(!has_GetEntityAPI)
|
||||
has_GetEntityAPI = strmatch(funcname, "GetEntityAPI");
|
||||
}
|
||||
// Check if metamod plugin
|
||||
else if(funcname[0] == 'M') {
|
||||
if(strmatch(funcname, "Meta_Init") ||
|
||||
strmatch(funcname, "Meta_Query") ||
|
||||
strmatch(funcname, "Meta_Attach") ||
|
||||
strmatch(funcname, "Meta_Detach")) {
|
||||
// Metamod plugin.. is not gamedll
|
||||
META_DEBUG(5, ("is_gamedll(%s): Detected Metamod plugin, library exports [%s].", filename, funcname));
|
||||
|
||||
UnmapViewOfFile(mapview);
|
||||
CloseHandle(hMap);
|
||||
CloseHandle(hFile);
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UnmapViewOfFile(mapview);
|
||||
CloseHandle(hMap);
|
||||
CloseHandle(hFile);
|
||||
|
||||
// Check if gamedll
|
||||
if(has_GiveFnptrsToDll && (has_GetEntityAPI2 || has_GetEntityAPI)) {
|
||||
// This is gamedll!
|
||||
META_DEBUG(5, ("is_gamedll(%s): Detected GameDLL.", filename));
|
||||
|
||||
return(mTRUE);
|
||||
} else {
|
||||
META_DEBUG(5, ("is_gamedll(%s): Library isn't GameDLL.", filename));
|
||||
|
||||
return(mFALSE);
|
||||
}
|
||||
}
|
||||
@@ -1,234 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
||||
*
|
||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#ifndef __USE_GNU
|
||||
#define __USE_GNU
|
||||
#endif
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <sys/mman.h>
|
||||
#define PAGE_SIZE 4096UL
|
||||
#define PAGE_MASK (~(PAGE_SIZE-1))
|
||||
#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
|
||||
#include <pthread.h>
|
||||
#include <link.h>
|
||||
|
||||
#include "osdep.h"
|
||||
#include "osdep_p.h"
|
||||
#include "log_meta.h" // META_LOG, etc
|
||||
#include "support_meta.h"
|
||||
|
||||
//
|
||||
// Linux code for dynamic linkents
|
||||
// -- by Jussi Kivilinna
|
||||
//
|
||||
|
||||
//opcode, e9, + sizeof pointer
|
||||
#define BYTES_SIZE (1 + sizeof(void*))
|
||||
|
||||
typedef void * (*dlsym_func)(void * module, const char * funcname);
|
||||
|
||||
static void * gamedll_module_handle = 0;
|
||||
static void * metamod_module_handle = 0;
|
||||
|
||||
//pointer to original dlsym
|
||||
static dlsym_func dlsym_original;
|
||||
|
||||
//contains jmp to replacement_dlsym @dlsym_original
|
||||
static unsigned char dlsym_new_bytes[BYTES_SIZE];
|
||||
|
||||
//contains original bytes of dlsym
|
||||
static unsigned char dlsym_old_bytes[BYTES_SIZE];
|
||||
|
||||
//Mutex for our protection
|
||||
static pthread_mutex_t mutex_replacement_dlsym = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
||||
|
||||
//constructs new jmp forwarder
|
||||
inline void construct_jmp_instruction(void *x, void *place, void* target)
|
||||
{
|
||||
((unsigned char *)x)[0] = 0xe9;
|
||||
*(unsigned long *)((char *)x + 1) = (unsigned long)target - ((unsigned long)place + 5);
|
||||
}
|
||||
|
||||
//checks if pointer x points to jump forwarder
|
||||
inline bool is_code_trampoline_jmp_opcode(void *x)
|
||||
{
|
||||
return (((unsigned char *)x)[0] == 0xff || ((unsigned char *)x)[1] == 0x25);
|
||||
}
|
||||
|
||||
//extracts pointer from "jmp dword ptr[pointer]"
|
||||
inline void * extract_function_pointer_from_trampoline_jmp(void *x)
|
||||
{
|
||||
return (**(void***)((char *)(x) + 2));
|
||||
}
|
||||
|
||||
//
|
||||
//restores old dlsym
|
||||
//
|
||||
inline void DLLINTERNAL restore_original_dlsym(void)
|
||||
{
|
||||
//Copy old dlsym bytes back
|
||||
memcpy((void*)dlsym_original, dlsym_old_bytes, BYTES_SIZE);
|
||||
}
|
||||
|
||||
//
|
||||
//resets new dlsym
|
||||
//
|
||||
inline void DLLINTERNAL reset_dlsym_hook(void)
|
||||
{
|
||||
//Copy new dlsym bytes back
|
||||
memcpy((void*)dlsym_original, dlsym_new_bytes, BYTES_SIZE);
|
||||
}
|
||||
|
||||
//
|
||||
// Replacement dlsym function
|
||||
//
|
||||
static void * __replacement_dlsym(void * module, const char * funcname)
|
||||
{
|
||||
//these are needed in case dlsym calls dlsym, default one doesn't do
|
||||
//it but some LD_PRELOADed library that hooks dlsym might actually
|
||||
//do so.
|
||||
static int is_original_restored = 0;
|
||||
int was_original_restored = is_original_restored;
|
||||
|
||||
//Lock before modifing original dlsym
|
||||
pthread_mutex_lock(&mutex_replacement_dlsym);
|
||||
|
||||
//restore old dlsym
|
||||
if(!is_original_restored)
|
||||
{
|
||||
restore_original_dlsym();
|
||||
|
||||
is_original_restored = 1;
|
||||
}
|
||||
|
||||
//check if we should hook this call
|
||||
if(module != metamod_module_handle || !metamod_module_handle || !gamedll_module_handle)
|
||||
{
|
||||
//no metamod/gamedll module? should we remove hook now?
|
||||
void * retval = dlsym_original(module, funcname);
|
||||
|
||||
if(metamod_module_handle && gamedll_module_handle)
|
||||
{
|
||||
if(!was_original_restored)
|
||||
{
|
||||
//reset dlsym hook
|
||||
reset_dlsym_hook();
|
||||
|
||||
is_original_restored = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//no metamod/gamedll module? should we remove hook now by not reseting it back?
|
||||
}
|
||||
|
||||
//unlock
|
||||
pthread_mutex_unlock(&mutex_replacement_dlsym);
|
||||
|
||||
return(retval);
|
||||
}
|
||||
|
||||
//dlsym on metamod module
|
||||
void * func = dlsym_original(module, funcname);
|
||||
|
||||
if(!func)
|
||||
{
|
||||
//function not in metamod module, try gamedll
|
||||
func = dlsym_original(gamedll_module_handle, funcname);
|
||||
}
|
||||
|
||||
if(!was_original_restored)
|
||||
{
|
||||
//reset dlsym hook
|
||||
reset_dlsym_hook();
|
||||
|
||||
is_original_restored = 0;
|
||||
}
|
||||
|
||||
//unlock
|
||||
pthread_mutex_unlock(&mutex_replacement_dlsym);
|
||||
|
||||
return(func);
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize
|
||||
//
|
||||
int DLLINTERNAL init_linkent_replacement(DLHANDLE MetamodHandle, DLHANDLE GameDllHandle)
|
||||
{
|
||||
metamod_module_handle = MetamodHandle;
|
||||
gamedll_module_handle = GameDllHandle;
|
||||
|
||||
// dlsym is already known to be pointing to valid function, we loaded gamedll using it earlier!
|
||||
void * sym_ptr = (void*)&dlsym;
|
||||
while(is_code_trampoline_jmp_opcode(sym_ptr)) {
|
||||
sym_ptr = extract_function_pointer_from_trampoline_jmp(sym_ptr);
|
||||
}
|
||||
|
||||
dlsym_original = (dlsym_func)sym_ptr;
|
||||
|
||||
//Backup old bytes of "dlsym" function
|
||||
memcpy(dlsym_old_bytes, (void*)dlsym_original, BYTES_SIZE);
|
||||
|
||||
//Construct new bytes: "jmp offset[replacement_sendto] @ sendto_original"
|
||||
construct_jmp_instruction((void*)&dlsym_new_bytes[0], (void*)dlsym_original, (void*)&__replacement_dlsym);
|
||||
|
||||
//Check if bytes overlap page border.
|
||||
unsigned long start_of_page = PAGE_ALIGN((long)dlsym_original) - PAGE_SIZE;
|
||||
unsigned long size_of_pages = 0;
|
||||
|
||||
if((unsigned long)dlsym_original + BYTES_SIZE > PAGE_ALIGN((unsigned long)dlsym_original))
|
||||
{
|
||||
//bytes are located on two pages
|
||||
size_of_pages = PAGE_SIZE*2;
|
||||
}
|
||||
else
|
||||
{
|
||||
//bytes are located entirely on one page.
|
||||
size_of_pages = PAGE_SIZE;
|
||||
}
|
||||
|
||||
//Remove PROT_READ restriction
|
||||
if(mprotect((void*)start_of_page, size_of_pages, PROT_READ|PROT_WRITE|PROT_EXEC))
|
||||
{
|
||||
META_ERROR("Couldn't initialize dynamic linkents, mprotect failed: %i. Exiting...", errno);
|
||||
return(0);
|
||||
}
|
||||
|
||||
//Write our own jmp-forwarder on "dlsym"
|
||||
reset_dlsym_hook();
|
||||
|
||||
//done
|
||||
return(1);
|
||||
}
|
||||
@@ -1,245 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
||||
*
|
||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <extdll.h> // always
|
||||
#include "osdep.h"
|
||||
|
||||
#include "log_meta.h" // META_LOG, etc
|
||||
#include "support_meta.h"
|
||||
|
||||
|
||||
//
|
||||
// Win32 code for dynamic linkents
|
||||
// -- by Jussi Kivilinna
|
||||
//
|
||||
|
||||
//
|
||||
// Reads metamod.dll and game.dll function export tables and combines theim to
|
||||
// single table that replaces metamod.dll's original table.
|
||||
//
|
||||
|
||||
typedef struct sort_names_s {
|
||||
unsigned long name;
|
||||
unsigned short nameOrdinal;
|
||||
} sort_names_t;
|
||||
|
||||
//relative virtual address to virtual address
|
||||
#define rva_to_va(base, rva) ((unsigned long)base + (unsigned long)rva)
|
||||
//virtual address to relative virtual address
|
||||
#define va_to_rva(base, va) ((unsigned long)va - (unsigned long)base)
|
||||
|
||||
//
|
||||
// Checks module signatures and return ntheaders pointer for valid module
|
||||
//
|
||||
static IMAGE_NT_HEADERS * DLLINTERNAL_NOVIS get_ntheaders(HMODULE module)
|
||||
{
|
||||
union {
|
||||
unsigned long mem;
|
||||
IMAGE_DOS_HEADER * dos;
|
||||
IMAGE_NT_HEADERS * pe;
|
||||
} mem;
|
||||
|
||||
//Check if valid dos header
|
||||
mem.mem = (unsigned long)module;
|
||||
if(IsBadReadPtr(mem.dos, sizeof(*mem.dos)) || mem.dos->e_magic != IMAGE_DOS_SIGNATURE)
|
||||
return(0);
|
||||
|
||||
//Get and check pe header
|
||||
mem.mem = rva_to_va(module, mem.dos->e_lfanew);
|
||||
if(IsBadReadPtr(mem.pe, sizeof(*mem.pe)) || mem.pe->Signature != IMAGE_NT_SIGNATURE)
|
||||
return(0);
|
||||
|
||||
return(mem.pe);
|
||||
}
|
||||
|
||||
//
|
||||
// Returns export table for valid module
|
||||
//
|
||||
static IMAGE_EXPORT_DIRECTORY * DLLINTERNAL_NOVIS get_export_table(HMODULE module)
|
||||
{
|
||||
union {
|
||||
unsigned long mem;
|
||||
void * pvoid;
|
||||
IMAGE_DOS_HEADER * dos;
|
||||
IMAGE_NT_HEADERS * pe;
|
||||
IMAGE_EXPORT_DIRECTORY * export_dir;
|
||||
} mem;
|
||||
|
||||
//Check module
|
||||
mem.pe = get_ntheaders(module);
|
||||
if(!mem.pe)
|
||||
return(0);
|
||||
|
||||
//Check for exports
|
||||
if(!mem.pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
|
||||
return(0);
|
||||
|
||||
mem.mem = rva_to_va(module, mem.pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
||||
if(IsBadReadPtr(mem.export_dir, sizeof(*mem.export_dir)))
|
||||
return(0);
|
||||
|
||||
return(mem.export_dir);
|
||||
}
|
||||
|
||||
//
|
||||
// Sort function for qsort
|
||||
//
|
||||
static int sort_names_list(const sort_names_t * A, const sort_names_t * B)
|
||||
{
|
||||
const char * str_A = (const char *)A->name;
|
||||
const char * str_B = (const char *)B->name;
|
||||
|
||||
return(mm_strcmp(str_A, str_B));
|
||||
}
|
||||
|
||||
//
|
||||
// Combines moduleMM and moduleGame export tables and replaces moduleMM table with new one
|
||||
//
|
||||
static int DLLINTERNAL_NOVIS combine_module_export_tables(HMODULE moduleMM, HMODULE moduleGame)
|
||||
{
|
||||
IMAGE_EXPORT_DIRECTORY * exportMM;
|
||||
IMAGE_EXPORT_DIRECTORY * exportGame;
|
||||
|
||||
unsigned long newNumberOfFunctions;
|
||||
unsigned long newNumberOfNames;
|
||||
unsigned long * newFunctions;
|
||||
unsigned long * newNames;
|
||||
unsigned short * newNameOrdinals;
|
||||
sort_names_t * newSort;
|
||||
|
||||
unsigned long i;
|
||||
unsigned long u;
|
||||
unsigned long funcCount;
|
||||
unsigned long nameCount;
|
||||
unsigned long listFix;
|
||||
|
||||
//Get export tables
|
||||
exportMM = get_export_table(moduleMM);
|
||||
exportGame = get_export_table(moduleGame);
|
||||
if(!exportMM || !exportGame)
|
||||
{
|
||||
META_ERROR("Couldn't initialize dynamic linkents, exportMM: %i, exportGame: %i. Exiting...", exportMM, exportGame);
|
||||
return(0);
|
||||
}
|
||||
|
||||
//setup new export table
|
||||
newNumberOfFunctions = exportMM->NumberOfFunctions + exportGame->NumberOfFunctions;
|
||||
newNumberOfNames = exportMM->NumberOfNames + exportGame->NumberOfNames;
|
||||
|
||||
//alloc lists
|
||||
*(void**)&newFunctions = calloc(1, newNumberOfFunctions * sizeof(*newFunctions));
|
||||
*(void**)&newSort = calloc(1, newNumberOfNames * sizeof(*newSort));
|
||||
|
||||
//copy moduleMM to new export
|
||||
for(funcCount = 0; funcCount < exportMM->NumberOfFunctions; funcCount++)
|
||||
newFunctions[funcCount] = rva_to_va(moduleMM, ((unsigned long*)rva_to_va(moduleMM, exportMM->AddressOfFunctions))[funcCount]);
|
||||
for(nameCount = 0; nameCount < exportMM->NumberOfNames; nameCount++)
|
||||
{
|
||||
//fix name address
|
||||
newSort[nameCount].name = rva_to_va(moduleMM, ((unsigned long*)rva_to_va(moduleMM, exportMM->AddressOfNames))[nameCount]);
|
||||
//ordinal is index to function list
|
||||
newSort[nameCount].nameOrdinal = ((unsigned short *)rva_to_va(moduleMM, exportMM->AddressOfNameOrdinals))[nameCount];
|
||||
}
|
||||
|
||||
//copy moduleGame to new export
|
||||
for(i = 0; i < exportGame->NumberOfFunctions; i++)
|
||||
newFunctions[funcCount + i] = rva_to_va(moduleGame, ((unsigned long*)rva_to_va(moduleGame, exportGame->AddressOfFunctions))[i]);
|
||||
for(i = 0, listFix = 0; i < exportGame->NumberOfNames; i++)
|
||||
{
|
||||
const char * name = (const char *)rva_to_va(moduleGame, ((unsigned long*)rva_to_va(moduleGame, exportGame->AddressOfNames))[i]);
|
||||
//Check if name already in the list
|
||||
for(u = 0; u < nameCount; u++)
|
||||
{
|
||||
if(!strcasecmp(name, (const char*)newSort[u].name))
|
||||
{
|
||||
listFix -= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(u < nameCount) //already in the list.. skip
|
||||
continue;
|
||||
|
||||
newSort[nameCount + i + listFix].name = (unsigned long)name;
|
||||
newSort[nameCount + i + listFix].nameOrdinal = (unsigned short)funcCount + ((unsigned short *)rva_to_va(moduleGame, exportGame->AddressOfNameOrdinals))[i];
|
||||
}
|
||||
|
||||
//set new number
|
||||
newNumberOfNames = nameCount + i + listFix;
|
||||
|
||||
//sort names list
|
||||
qsort(newSort, newNumberOfNames, sizeof(*newSort), (int(*)(const void*, const void*))&sort_names_list);
|
||||
|
||||
//make newNames and newNameOrdinals lists (VirtualAlloc so we dont waste heap memory to stuff that isn't freed)
|
||||
*(void**)&newNames = VirtualAlloc(0, newNumberOfNames * sizeof(*newNames), MEM_COMMIT, PAGE_READWRITE);
|
||||
*(void**)&newNameOrdinals = VirtualAlloc(0, newNumberOfNames * sizeof(*newNameOrdinals), MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
for(i = 0; i < newNumberOfNames; i++)
|
||||
{
|
||||
newNames[i] = newSort[i].name;
|
||||
newNameOrdinals[i] = newSort[i].nameOrdinal;
|
||||
}
|
||||
|
||||
free(newSort);
|
||||
|
||||
//translate VAs to RVAs
|
||||
for(i = 0; i < newNumberOfFunctions; i++)
|
||||
newFunctions[i] = va_to_rva(moduleMM, newFunctions[i]);
|
||||
for(i = 0; i < newNumberOfNames; i++)
|
||||
{
|
||||
newNames[i] = va_to_rva(moduleMM, newNames[i]);
|
||||
newNameOrdinals[i] = (unsigned short)va_to_rva(moduleMM, newNameOrdinals[i]);
|
||||
}
|
||||
|
||||
DWORD OldProtect;
|
||||
if(!VirtualProtect(exportMM, sizeof(*exportMM), PAGE_READWRITE, &OldProtect))
|
||||
{
|
||||
META_ERROR("Couldn't initialize dynamic linkents, VirtualProtect failed: %i. Exiting...", GetLastError());
|
||||
return(0);
|
||||
}
|
||||
|
||||
exportMM->Base = 1;
|
||||
exportMM->NumberOfFunctions = newNumberOfFunctions;
|
||||
exportMM->NumberOfNames = newNumberOfNames;
|
||||
*(unsigned long*)&(exportMM->AddressOfFunctions) = va_to_rva(moduleMM, newFunctions);
|
||||
*(unsigned long*)&(exportMM->AddressOfNames) = va_to_rva(moduleMM, newNames);
|
||||
*(unsigned long*)&(exportMM->AddressOfNameOrdinals) = va_to_rva(moduleMM, newNameOrdinals);
|
||||
|
||||
VirtualProtect(exportMM, sizeof(*exportMM), OldProtect, &OldProtect);
|
||||
return(1);
|
||||
}
|
||||
|
||||
//
|
||||
// ...
|
||||
//
|
||||
int DLLINTERNAL init_linkent_replacement(DLHANDLE moduleMetamod, DLHANDLE moduleGame)
|
||||
{
|
||||
return(combine_module_export_tables(moduleMetamod, moduleGame));
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2004-2006 Jussi Kivilinna
|
||||
*
|
||||
* This file is part of "Metamod All-Mod-Support"-patch for Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef linux
|
||||
// enable extra routines in system header files, like dladdr
|
||||
# ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
# endif
|
||||
#include <dlfcn.h> // dlopen, dladdr, etc
|
||||
#endif /* linux */
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "osdep_p.h" // me
|
||||
#include "support_meta.h" // STRNCPY
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
// MSVC doesn't provide "dirent.h" header. These functions wrap opendir/readdir/closedir
|
||||
// functions to FindFirst/FindNext/FindClose win32api-functions.
|
||||
DIR * DLLINTERNAL my_opendir(const char *path)
|
||||
{
|
||||
char search_path[MAX_PATH];
|
||||
DIR *dir;
|
||||
|
||||
// Add wildcards to path
|
||||
safevoid_snprintf(search_path, sizeof(search_path), "%s\\*.*", path);
|
||||
|
||||
// Get memory for new DIR object
|
||||
dir = (DIR*)calloc(1, sizeof(DIR));
|
||||
|
||||
// Start searching
|
||||
dir->handle = FindFirstFileA(search_path, &dir->find_data);
|
||||
if(dir->handle == INVALID_HANDLE_VALUE) {
|
||||
free(dir);
|
||||
return(0);
|
||||
}
|
||||
|
||||
// Found file
|
||||
dir->not_found = 0;
|
||||
|
||||
return(dir);
|
||||
}
|
||||
|
||||
struct dirent * DLLINTERNAL my_readdir(DIR *dir)
|
||||
{
|
||||
// If not found stop
|
||||
if(!dir || dir->not_found)
|
||||
return(0);
|
||||
|
||||
// Set filename
|
||||
STRNCPY(dir->ent.d_name, dir->find_data.cFileName, sizeof(dir->ent.d_name));
|
||||
|
||||
// Search next
|
||||
dir->not_found = !FindNextFileA(dir->handle, &dir->find_data);
|
||||
|
||||
return(&dir->ent);
|
||||
}
|
||||
|
||||
void DLLINTERNAL my_closedir(DIR *dir)
|
||||
{
|
||||
if(!dir)
|
||||
return;
|
||||
|
||||
FindClose(dir->handle);
|
||||
free(dir);
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
//get module handle of memptr
|
||||
#ifdef linux
|
||||
DLHANDLE DLLINTERNAL get_module_handle_of_memptr(void * memptr)
|
||||
{
|
||||
Dl_info dli;
|
||||
memset(&dli, 0, sizeof(dli));
|
||||
|
||||
if(dladdr(memptr, &dli))
|
||||
return(dlopen(dli.dli_fname, RTLD_NOW));
|
||||
else
|
||||
return((void*)0);
|
||||
}
|
||||
#else
|
||||
DLHANDLE DLLINTERNAL get_module_handle_of_memptr(void * memptr)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION MBI;
|
||||
|
||||
if(!VirtualQuery(memptr, &MBI, sizeof(MBI)))
|
||||
return(NULL);
|
||||
if(MBI.State != MEM_COMMIT)
|
||||
return(NULL);
|
||||
if(!MBI.AllocationBase)
|
||||
return(NULL);
|
||||
|
||||
return((DLHANDLE)MBI.AllocationBase);
|
||||
}
|
||||
#endif /* linux */
|
||||
@@ -1,228 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// reg_support.cpp - support for things "registered" by plugins (console
|
||||
// cmds, cvars, msgs, etc)
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef linux
|
||||
// enable extra routines in system header files, like strsignal
|
||||
# ifndef _GNU_SOURCE
|
||||
# define _GNU_SOURCE
|
||||
# endif
|
||||
#endif /* linux */
|
||||
|
||||
#include <string.h> // strsignal, etc
|
||||
|
||||
#include <extdll.h> // always
|
||||
#include "sdk_util.h" // REG_SVR_COMMAND, etc
|
||||
|
||||
#include "reg_support.h" // me
|
||||
#include "metamod.h" // RegCmds, g_Players, etc
|
||||
#include "log_meta.h" // META_ERROR, etc
|
||||
|
||||
// "Register" support.
|
||||
//
|
||||
// This code is necessary to support the different "register" engine
|
||||
// functions that can be called by plugins, so that the plugins can be
|
||||
// safely unloaded without incurring segmentation faults.
|
||||
//
|
||||
// The problem was that, when a plugin called, say:
|
||||
// REG_SVR_COMMAND("stub_version", svr_stub_version);
|
||||
//
|
||||
// the engine stored the address to the "stub_version" string, as well as,
|
||||
// of course, the svr_stub_version() function pointer. If the plugin was
|
||||
// unloaded, and dlclose()'d, the memory locations for both the string and
|
||||
// function became invalid and unavailable. If the engine tried to
|
||||
// strcmp() against the string, or tried to call the function pointer, it
|
||||
// generated a segfault and killed the process.
|
||||
//
|
||||
// The solution used here is to create strings and functions allocated
|
||||
// locally, in metamod.dll, which won't become unavailable or invalid due
|
||||
// to a dlclose(). These local copies are passed to the engine instead of
|
||||
// those allocated in the plugin DLLs. Thus, when a plugin is later
|
||||
// unloaded and dlclose'd, the engine can still reference the memory
|
||||
// locations of registered strings and functions, without segfaulting.
|
||||
//
|
||||
// Now, what happens with a registered string or function after a plugin is
|
||||
// unloaded not quite as nice as I'd like.
|
||||
//
|
||||
// Console commands will print a message along the lines of:
|
||||
// [metamod: command '%s' unavailable; plugin unloaded]
|
||||
//
|
||||
// Cvars though, have their value unaffected. This can be convenient when
|
||||
// reloading a plugin, as the cvars keep their old values. However it can
|
||||
// also be confusing, as there is no indication when viewing/setting cvars
|
||||
// from the console that they no longer have an effect.
|
||||
//
|
||||
// Also note, the console commands for listing registered cmds and cvars
|
||||
// will try to show the name of the associated plugin.
|
||||
|
||||
|
||||
// Generic command handler, passed to the engine for any AddServerCommand
|
||||
// calls made by the plugin. It finds the appropriate plugin function
|
||||
// pointer to call based on CMD_ARGV(0).
|
||||
void DLLHIDDEN meta_command_handler(void) {
|
||||
MRegCmd *icmd;
|
||||
const char *cmd;
|
||||
|
||||
META_DEBUG(5, ("called: meta_command_handler; arg0=%s args='%s'", CMD_ARGV(0), CMD_ARGS()));
|
||||
cmd=CMD_ARGV(0);
|
||||
if(!cmd) {
|
||||
META_WARNING("Null command name in meta_command_handler() ??");
|
||||
return;
|
||||
}
|
||||
|
||||
icmd=RegCmds->find(cmd);
|
||||
if(!icmd) {
|
||||
META_WARNING("Couldn't find registered plugin command: %s", cmd);
|
||||
return;
|
||||
}
|
||||
if(icmd->call() != mTRUE)
|
||||
META_CONS("[metamod: command '%s' unavailable; plugin unloaded]", cmd);
|
||||
}
|
||||
|
||||
|
||||
// Replacement for engine routine AddServerCommand; called by plugins.
|
||||
// Rather then handing the engine the plugin's command string and function
|
||||
// pointer (both of which are allocated in the plugin DLL), this hands the
|
||||
// engine a command string and function pointer allocated locally (in the
|
||||
// metamod DLL).
|
||||
//
|
||||
// The string handed to the engine is just a strdup() of the plugin's
|
||||
// string. The function pointer handed to the engine is actually a pointer
|
||||
// to a generic command-handler function (see above).
|
||||
void DLLHIDDEN meta_AddServerCommand(char *cmd_name, void (*function) (void)) {
|
||||
MPlugin *iplug=NULL;
|
||||
MRegCmd *icmd=NULL;
|
||||
|
||||
META_DEBUG(4, ("called: meta_AddServerCommand; cmd_name=%s, function=%d", cmd_name, function));
|
||||
|
||||
// try to find which plugin is registering this command
|
||||
if(!(iplug=Plugins->find_memloc((void *)function))) {
|
||||
// if this isn't supported on this OS, don't log an error
|
||||
if(meta_errno != ME_OSNOTSUP)
|
||||
META_WARNING("Failed to find memloc for regcmd '%s'", cmd_name);
|
||||
}
|
||||
|
||||
// See if this command was previously registered, ie a "reloaded" plugin.
|
||||
icmd=RegCmds->find(cmd_name);
|
||||
if(!icmd) {
|
||||
// If not found, add.
|
||||
icmd=RegCmds->add(cmd_name);
|
||||
if(!icmd) {
|
||||
// error details logged in add()
|
||||
return;
|
||||
}
|
||||
// Only register if not previously registered..
|
||||
REG_SVR_COMMAND(icmd->name, meta_command_handler);
|
||||
}
|
||||
|
||||
icmd->pfnCmd=function;
|
||||
icmd->status=RG_VALID;
|
||||
// Store which plugin this is for, if we know. We can use '0' for
|
||||
// unknown plugin, since plugin index starts at 1.
|
||||
if(iplug)
|
||||
icmd->plugid = iplug->index;
|
||||
else
|
||||
icmd->plugid = 0;
|
||||
}
|
||||
|
||||
|
||||
// Replacement for engine routine CVarRegister; called by plugins. Rather
|
||||
// then handing the engine the plugin's cvar structure (which is allocated
|
||||
// in the plugin DLL), this hands the engine a cvar structure allocated
|
||||
// locally (in the metamod DLL).
|
||||
//
|
||||
// The cvar handed to the engine is globally allocated in the metamod.dll;
|
||||
// the "name" and "string" fields are strdup()'s of the plugin's strings.
|
||||
// Note that, once this is done, the cvar_t allocated in the plugin is no
|
||||
// longer used for _anything_. As long as everything sets/gets the cvar
|
||||
// values via the engine functions, this will work fine. If the plugin
|
||||
// code tries to _directly_ read/set the fields of its own cvar structures,
|
||||
// it will fail to work properly.
|
||||
void DLLHIDDEN meta_CVarRegister(cvar_t *pCvar) {
|
||||
MPlugin *iplug=NULL;
|
||||
MRegCvar *icvar=NULL;
|
||||
|
||||
META_DEBUG(4, ("called: meta_CVarRegister; name=%s", pCvar->name));
|
||||
|
||||
// try to find which plugin is registering this cvar
|
||||
if(!(iplug=Plugins->find_memloc((void *)pCvar))) {
|
||||
// if this isn't supported on this OS, don't log an error
|
||||
if(meta_errno != ME_OSNOTSUP)
|
||||
// Note: if cvar_t was malloc'd by the plugin, we can't
|
||||
// determine the calling plugin. Thus, this becomes a Debug
|
||||
// rather than Error message.
|
||||
META_DEBUG(1, ("Failed to find memloc for regcvar '%s'",
|
||||
pCvar->name));
|
||||
}
|
||||
|
||||
// See if this cvar was previously registered, ie a "reloaded" plugin.
|
||||
icvar=RegCvars->find(pCvar->name);
|
||||
if(!icvar) {
|
||||
// If not found, add.
|
||||
icvar=RegCvars->add(pCvar->name);
|
||||
if(!icvar) {
|
||||
// error details logged in add()
|
||||
return;
|
||||
}
|
||||
// Reset to given value
|
||||
icvar->set(pCvar);
|
||||
CVAR_REGISTER(icvar->data);
|
||||
}
|
||||
// Note: if not a new cvar, then we don't set the values, and just keep
|
||||
// the pre-existing value.
|
||||
|
||||
icvar->status=RG_VALID;
|
||||
// Store which plugin this is for, if we know. Use '0' for unknown
|
||||
// plugin, as plugin index starts at 1.
|
||||
if(iplug)
|
||||
icvar->plugid = iplug->index;
|
||||
else
|
||||
icvar->plugid = 0;
|
||||
}
|
||||
|
||||
|
||||
// Replacement for engine routine RegUserMsg; called by plugins.
|
||||
int DLLHIDDEN meta_RegUserMsg(const char *pszName, int iSize) {
|
||||
return(REG_USER_MSG(strdup(pszName), iSize));
|
||||
}
|
||||
|
||||
|
||||
// Intercept and record queries
|
||||
void DLLHIDDEN meta_QueryClientCvarValue(const edict_t *player, const char *cvarName) {
|
||||
g_Players.set_player_cvar_query(player, cvarName);
|
||||
|
||||
(*g_engfuncs.pfnQueryClientCvarValue)(player, cvarName);
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
// vi: set ts=4 sw=4 ft=c :
|
||||
// vim: set tw=75 :
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
// see:
|
||||
// http://msdn.microsoft.com/library/psdk/winui/rc_7x2d.htm
|
||||
|
||||
#include <winver.h>
|
||||
#include "info_name.h"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION RC_VERS_DWORD
|
||||
PRODUCTVERSION RC_VERS_DWORD
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS__WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "Comments", RC_COMMENTS "\0"
|
||||
VALUE "CompanyName", VAUTHOR "\0"
|
||||
VALUE "FileDescription", RC_DESC "\0"
|
||||
VALUE "FileVersion", VVERSION "\0"
|
||||
VALUE "InternalName", RC_INTERNAL "\0"
|
||||
VALUE "LegalCopyright", RC_COPYRIGHT "\0"
|
||||
VALUE "License", RC_LICENSE "\0"
|
||||
VALUE "OriginalFilename", RC_FILENAME "\0"
|
||||
VALUE "PrivateBuild", "\0"
|
||||
VALUE "ProductName", VNAME "\0"
|
||||
VALUE "ProductVersion", VVERSION "\0"
|
||||
VALUE "SpecialBuild", OPT_TYPE "\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
@@ -1,125 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// sdk_util.cpp - utility routines from HL SDK util.cpp
|
||||
|
||||
// Selected portions of dlls/util.cpp from SDK 2.1.
|
||||
// Functions copied from there as needed...
|
||||
// And modified to avoid buffer overflows (argh).
|
||||
// Also modified to remove dependency on CBaseEntity class.
|
||||
|
||||
/***
|
||||
*
|
||||
* Copyright (c) 1999, 2000 Valve LLC. All rights reserved.
|
||||
*
|
||||
* This product contains software technology licensed from Id
|
||||
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Use, distribution, and modification of this source code and/or resulting
|
||||
* object code is restricted to non-commercial enhancements to products from
|
||||
* Valve LLC. All other use, distribution, or modification is prohibited
|
||||
* without written permission from Valve LLC.
|
||||
*
|
||||
****/
|
||||
/*
|
||||
|
||||
===== util.cpp ========================================================
|
||||
|
||||
Utility code. Really not optional after all.
|
||||
|
||||
*/
|
||||
|
||||
#include <extdll.h>
|
||||
#include "sdk_util.h"
|
||||
|
||||
#include <string.h> // for strncpy(), etc
|
||||
|
||||
#include "osdep.h" // win32 vsnprintf, etc
|
||||
|
||||
const char * DLLINTERNAL META_UTIL_VarArgs(const char *format, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
static char string[4096];
|
||||
|
||||
va_start(argptr, format);
|
||||
safevoid_vsnprintf(string, sizeof(string), format, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
return(string);
|
||||
}
|
||||
|
||||
short DLLINTERNAL FixedSigned16(float value, float scale)
|
||||
{
|
||||
int output;
|
||||
|
||||
output = (int)(value * scale);
|
||||
|
||||
if(output > 32767)
|
||||
output = 32767;
|
||||
|
||||
if(output < -32768)
|
||||
output = -32768;
|
||||
|
||||
return((short)output);
|
||||
}
|
||||
|
||||
unsigned short DLLINTERNAL FixedUnsigned16(float value, float scale)
|
||||
{
|
||||
int output;
|
||||
|
||||
output = (int)(value * scale);
|
||||
if(output < 0)
|
||||
output = 0;
|
||||
if(output > 0xFFFF)
|
||||
output = 0xFFFF;
|
||||
|
||||
return((unsigned short)output);
|
||||
}
|
||||
|
||||
|
||||
void DLLINTERNAL META_UTIL_HudMessage(edict_t *pEntity, const hudtextparms_t &textparms, const char *pMessage)
|
||||
{
|
||||
if(fast_FNullEnt(pEntity) || pEntity->free)
|
||||
return;
|
||||
|
||||
MESSAGE_BEGIN( MSG_ONE, SVC_TEMPENTITY, NULL, pEntity );
|
||||
WRITE_BYTE( TE_TEXTMESSAGE );
|
||||
WRITE_BYTE( textparms.channel & 0xFF );
|
||||
|
||||
WRITE_SHORT( FixedSigned16( textparms.x, 1<<13 ) );
|
||||
WRITE_SHORT( FixedSigned16( textparms.y, 1<<13 ) );
|
||||
WRITE_BYTE( textparms.effect );
|
||||
|
||||
WRITE_BYTE( textparms.r1 );
|
||||
WRITE_BYTE( textparms.g1 );
|
||||
WRITE_BYTE( textparms.b1 );
|
||||
WRITE_BYTE( textparms.a1 );
|
||||
|
||||
WRITE_BYTE( textparms.r2 );
|
||||
WRITE_BYTE( textparms.g2 );
|
||||
WRITE_BYTE( textparms.b2 );
|
||||
WRITE_BYTE( textparms.a2 );
|
||||
|
||||
WRITE_SHORT( FixedUnsigned16( textparms.fadeinTime, 1<<8 ) );
|
||||
WRITE_SHORT( FixedUnsigned16( textparms.fadeoutTime, 1<<8 ) );
|
||||
WRITE_SHORT( FixedUnsigned16( textparms.holdTime, 1<<8 ) );
|
||||
|
||||
if(textparms.effect == 2)
|
||||
WRITE_SHORT( FixedUnsigned16( textparms.fxTime, 1<<8 ) );
|
||||
|
||||
if(strlen( pMessage ) < 512)
|
||||
{
|
||||
WRITE_STRING( pMessage );
|
||||
}
|
||||
else
|
||||
{
|
||||
char tmp[512];
|
||||
strncpy( tmp, pMessage, 511 );
|
||||
tmp[511] = 0;
|
||||
WRITE_STRING( tmp );
|
||||
}
|
||||
MESSAGE_END();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// studio.cpp - player model blending interfaces
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
//Jussi Kivilinna: This forwarder function to gamedll is not needed anymore, dynamic
|
||||
// linkent code handles this too!
|
||||
@@ -1,121 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// support_meta.cpp - generic support routines
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <extdll.h> // always
|
||||
|
||||
#include "metamod.h" // GameDLL
|
||||
#include "support_meta.h" // me
|
||||
#include "osdep.h" // sleep, etc
|
||||
|
||||
META_ERRNO meta_errno;
|
||||
|
||||
void DLLINTERNAL do_exit(int exitval) {
|
||||
sleep(3);
|
||||
exit(exitval);
|
||||
}
|
||||
|
||||
// Checks for a non-empty file, relative to the gamedir if necessary.
|
||||
// Formerly used LOAD_FILE_FOR_ME, which provided a simple way to check for
|
||||
// a file under the gamedir, but which would _also_ look in the sibling
|
||||
// "valve" directory, thus sometimes finding files that weren't desired.
|
||||
// Also, formerly named just "valid_file".
|
||||
//
|
||||
// Special-case-recognize "/dev/null" as a valid file.
|
||||
int DLLINTERNAL valid_gamedir_file(const char *path) {
|
||||
char buf[PATH_MAX];
|
||||
struct stat st;
|
||||
int ret, reg, size;
|
||||
|
||||
if(!path)
|
||||
return(FALSE);
|
||||
|
||||
if(strmatch(path, "/dev/null"))
|
||||
return(TRUE);
|
||||
|
||||
if(is_absolute_path(path))
|
||||
STRNCPY(buf, path, sizeof(buf));
|
||||
else
|
||||
safevoid_snprintf(buf, sizeof(buf), "%s/%s", GameDLL.gamedir, path);
|
||||
|
||||
ret=stat(buf, &st);
|
||||
if(ret != 0) {
|
||||
META_DEBUG(5, ("Unable to stat '%s': %s", buf, strerror(errno)));
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
reg=S_ISREG(st.st_mode);
|
||||
if(!reg) {
|
||||
META_DEBUG(5, ("Not a regular file: %s", buf));
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
size=st.st_size;
|
||||
if(!size) {
|
||||
META_DEBUG(5, ("Empty file: %s", buf));
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if(ret==0 && reg && size)
|
||||
return(TRUE);
|
||||
else
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
// Turns path into a full path:
|
||||
// - if not absolute, prepends gamedir
|
||||
// - calls realpath() to collapse ".." and such
|
||||
// - calls normalize_pathname() to fix backslashes, etc
|
||||
//
|
||||
// Much like realpath, buffer pointed to by fullpath is assumed to be
|
||||
// able to store a string of PATH_MAX length.
|
||||
char * DLLINTERNAL full_gamedir_path(const char *path, char *fullpath) {
|
||||
char buf[PATH_MAX];
|
||||
|
||||
// Build pathname from filename, plus gamedir if relative path.
|
||||
if(is_absolute_path(path))
|
||||
STRNCPY(buf, path, sizeof(buf));
|
||||
else
|
||||
safevoid_snprintf(buf, sizeof(buf), "%s/%s", GameDLL.gamedir, path);
|
||||
// Remove relative path components, if possible.
|
||||
if(!realpath(buf, fullpath)) {
|
||||
META_DEBUG(4, ("Unable to get realpath for '%s': %s", buf,
|
||||
str_os_error()));
|
||||
STRNCPY(fullpath, path, PATH_MAX);
|
||||
}
|
||||
// Replace backslashes, etc.
|
||||
normalize_pathname(fullpath);
|
||||
return(fullpath);
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
// vi: set ts=4 sw=4 :
|
||||
// vim: set tw=75 :
|
||||
|
||||
// vdate.cpp - compile-time version date
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2006 Will Day <willday@hpgx.net>
|
||||
*
|
||||
* This file is part of Metamod.
|
||||
*
|
||||
* Metamod is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Metamod is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Metamod; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "info_name.h" // for VNAME, VVERSION, etc
|
||||
#include "vdate.h"
|
||||
|
||||
|
||||
// Grab date/time of compile. The Makefile is set up to recompile this
|
||||
// module before each link, so that this will always indicate the time the
|
||||
// library was compiled and linked.
|
||||
|
||||
// This is in a separate file from vers_*, so it can be generically used by
|
||||
// multiple projects.
|
||||
|
||||
char const *COMPILE_TIME=__DATE__ ", " __TIME__;
|
||||
|
||||
#ifndef COMPILE_TZ
|
||||
#define COMPILE_TZ "EET"
|
||||
#endif
|
||||
|
||||
char const *COMPILE_TZONE = COMPILE_TZ;
|
||||
|
||||
// Include a string for /usr/bin/ident.
|
||||
|
||||
char const *vstring="\n$Pg: " VNAME " -- " VVERSION " | " __DATE__ " - " __TIME__ " $\n";
|
||||
Reference in New Issue
Block a user