#include "p4objects.h"
LINK_ENTITY_TO_CLASS( object_info, CObjectInfo)
void CObjectInfo :: Spawn( )
{
Precache( );
SET_MODEL( ENT(pev), STRING(pev->model) );
UTIL_SetOrigin( pev, pev->origin );
target = (Vector)pev->origin; //by default, we're already where we want to be.
UTIL_SetSize( pev, Vector(-30, -30, 38), Vector(30, 30, 90) ); //collision box!
level = 0;
pev->movetype = MOVETYPE_FLY;
/* This is the animating code. */
pev->sequence = LookupActivity (ACT_IDLE); //Use the ACT_IDLE sequence.
pev->frame = 0; //Start on frame 0.
pev->framerate = 1; //And set a framerate of 1.
/* */
pev->solid = SOLID_BBOX;
SetThink( Think );
SetTouch( Touch );
pev->nextthink = gpGlobals->time + 0.8;
nextRefreshTime = gpGlobals->time + 30;
}
/* The object_info is the only one that's in the world when the map starts up, so we need
* to precache everything, since the object_info will ultimately be spawning them later. */
void CObjectInfo :: Precache( )
{
/* Precache all the models, starting with this one. */
PRECACHE_MODEL( "models/info/w_info.mdl" );
PRECACHE_MODEL( "models/depot/w_depot.mdl" );
PRECACHE_MODEL( "models/dir/w_dir.mdl" );
PRECACHE_MODEL( "models/file/w_file.mdl");
PRECACHE_MODEL( "models/rev/w_edit.mdl" );
PRECACHE_MODEL( "models/rev/w_add.mdl" );
PRECACHE_MODEL( "models/rev/w_delete.mdl" );
PRECACHE_MODEL( "models/rev/w_integ.mdl" );
/* Before I put this next bit of code in, the program would lag for three
* seconds the first time I accessed Perforce. Now I have it in the precache
* function so it's not as noticeable - still not sure exactly why it's slow
* the first time, though. */
ClientLuser ui;
ClientApi client;
Error e;
client.Init( &e );
client.Run( "info", &ui );
client.Final( &e );
}
void CObjectInfo :: Think( void )
{
if (!IsInWorld())
{
UTIL_Remove( this );
return;
}
if (nextRefreshTime < gpGlobals->time)
{
ClientLuser ui;
ClientApi client;
Error e;
client.Init( &e );
client.Run( "info", &ui );
client.Final( &e );
nextRefreshTime += 30;
}
if (UTIL_VecUpdate( &(pev->origin), target ))
{
pev->nextthink = gpGlobals->time + 0.05;
UTIL_SetSize( pev, Vector(-30, -30, 38), Vector(30, 30, 90) ); //collision box!
}
else pev->nextthink = gpGlobals->time + 0.5;
}
void CObjectInfo :: Touch( CBaseEntity* Player )
{
CBasePlayer *pl;
CBaseEntity *be = CBaseEntity::Instance(Player->pev->owner);
if (Player->IsPlayer()) pl = (CBasePlayer*) Player;
else if (be->IsPlayer()) pl = (CBasePlayer*) be;
else return;
if (pl->m_flNextP4Time > gpGlobals->time) return;
if (Player->IsExpand()) {
Expand( pl );
return;
}
//after this point we just spit "p4 info" to player "pl".
//run the command "p4 info"
ClientLuser ui;
ClientApi client;
Error e;
StrBuf msg = StrBuf();
client.Init( &e );
if (e.GetSeverity()) {
e.Fmt(&msg);
UTIL_FatalHud(pl, msg.Text());
pl->m_flNextP4Time = gpGlobals->time + 20.0; //20 second delay on connect error
return;
}
client.Run( "info", &ui );
client.Final( &e );
if (e.GetSeverity()) {
e.Fmt(&msg);
UTIL_WarningHud(pl, msg.Text());
}
// Print contents of the message buffer
UTIL_PrintHud( pl, ui.message.Text());
pl->m_flNextP4Time = gpGlobals->time + 0.5; //0.5 second delay
}
void CObjectInfo :: Expand( CBasePlayer *pl)
{
if (level == 1) return;
UTIL_PrintHud( pl, "Expanding root node...\n");
killKids(this);
newLevel(1);
ClientDepotUser ui;
ui.specflag = FALSE;
ClientApi client;
Error e;
client.Init( &e );
if (e.GetSeverity()) {
StrBuf msg = StrBuf();
e.Fmt(&msg);
UTIL_FatalHud(pl, msg.Text());
pl->m_flNextP4Time = gpGlobals->time + 20.0;
return;
}
client.Run( "depots", &ui );
client.Final( &e );
if (e.GetSeverity()) {
StrBuf warn = StrBuf();
e.Fmt(&warn);
UTIL_WarningHud(pl, warn.Text());
}
StrBuf depot = ui.depots.SPop();
if (depot.Length() == 0) depot.Append("depot");
float ycoord = 0.0;
CObjectDepot *newdepot;
while (depot.Length() > 0)
{
newdepot = GetClassPtr( (CObjectDepot *)NULL );
depots.Append(newdepot);
newdepot->pev->classname = MAKE_STRING("object_depot");
newdepot->Spawn();
newdepot->pev->origin = pev->origin;
newdepot->target = target - Vector(0,0,100);
newdepot->target.y -= ycoord*100;
newdepot->path = depot;
newdepot->parent = this;
newdepot->pev->nextthink = gpGlobals->time;
depot = ui.depots.SPop();
ycoord++;
}
return;
}
void CObjectInfo :: newLevel( short newlev)
{
target.z += (newlev - level)*100;
level = newlev;
}
void CObjectInfo :: disown( CBaseEntity *child)
{
depots.EKill(child);
}
void CObjectInfo :: killKids( CBaseEntity *Caller )
{
BOOL callerFlag = FALSE;
CBaseEntity* kid = depots.EPop();
while (kid != NULL)
{
if (kid == Caller)
{
callerFlag = TRUE;
kid = depots.EPop();
continue;
}
kid -> killKids(this);
UTIL_Remove(kid);
kid = depots.EPop();
}
if (callerFlag) depots.Append(Caller);
}
| # | Change | User | Description | Committed | |
|---|---|---|---|---|---|
| #6 | 1689 | Sam Stafford |
Integrate 02.1 API and code cleanup to P4HL. Lots of work. Phew. |
||
| #5 | 1007 | Sam Stafford |
A stab at making P4HL a bit more accessible to Perforce novices. During the Precache() phase of the P4HL objects, a "p4 info" is executed. If this returns any errors, odds are there's no server there (I can't think of what other error "p4 info" would return). If this happens, use "public.perforce.com:1666" as the new port value for all future Perforce transactions during this session, and send a message to the console explaining this. |
||
| #4 | 1003 | Sam Stafford |
Different file types now displayed differently. Also flipped around the file model so that its text doesn't look backwards any more. |
||
| #3 | 986 | Sam Stafford |
If no depots are listed by "p4 depots", assume that there is one depot called "depot". |
||
| #2 | 971 | Sam Stafford | Have the ObjectInfo run a "p4 info" every 30 seconds. | ||
| #1 | 937 | Sam Stafford |
Renaming my guest directory to the more conventional sam_stafford. |
||
| //guest/samwise/p4hl/src/dlls/objectinfo.cpp | |||||
| #1 | 936 | Sam Stafford |
Adding P4HL to the public depot. See relnotes.txt for installation instructions; all relevant files are under p4hl/dist. Source code is under p4hl/src in the form of a VC++ project. |
||