2
3
mirror of https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git synced 2025-07-14 02:27:40 -04:00

Initial Commit of CyanWorlds.com Engine Open Source Client/Plugin

This commit is contained in:
JWPlatt
2011-03-12 12:34:52 -05:00
commit a20a222fc2
3976 changed files with 1301356 additions and 0 deletions

View File

@ -0,0 +1,924 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// Avatar Console Commands and Groups //
// //
//////////////////////////////////////////////////////////////////////////////
#ifdef PLASMA_EXTERNAL_RELEASE
#define LIMIT_CONSOLE_COMMANDS 1
#endif
#include "pfConsoleCmd.h"
#include "plgDispatch.h"
#include "pfConsole.h"
#include "hsResMgr.h"
#include "../pfMessage/plArmatureEffectMsg.h"
#include "../plMessage/plOneShotMsg.h"
#include "../plMessage/plAvatarMsg.h"
#include "../plMessage/plInputEventMsg.h"
#include "../plMessage/plSimStateMsg.h"
#include "../plMessage/plCCRMsg.h"
#include "../plMessage/plLinkToAgeMsg.h"
#include "../pnMessage/plNotifyMsg.h"
#include "../plModifier/plSpawnModifier.h"
#include "../plResMgr/plKeyFinder.h"
#include "../plAvatar/plArmatureMod.h"
#include "../plAvatar/plAvBrainCritter.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plAvatar/plAvBrainSwim.h"
#include "../plAvatar/plAvBrainGeneric.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plSeekPointMod.h"
#include "../plAvatar/plOneShotMod.h"
#include "../plAvatar/plAGAnim.h"
#include "../plAvatar/plAvBrainUser.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plAvatar/plNPCSpawnMod.h"
#include "../plAvatar/plAGAnimInstance.h"
#include "../plAvatar/plArmatureEffects.h"
#include "../plAvatar/plAvTaskSeek.h"
//#include "../plHavok1/plSimulationMgr.h"
#include "../pnNetCommon/plNetApp.h"
#include "../plNetClient/plNetClientMgr.h"
#include "../plDrawable/plInstanceDrawInterface.h"
#include "../plDrawable/plDrawableSpans.h"
#define PF_SANITY_CHECK( cond, msg ) { if( !( cond ) ) { PrintString( msg ); return; } }
//// This is here so Microsoft VC won't decide to "optimize" this file out
void pfConsoleCmdGroup::DummyAvatar( void )
{
}
/////////////////////////////////////////////////////////////////
//
// Please see pfConsoleCommands.cpp for detailed instructions on
// how to add console commands.
//
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
//
// UTILITIES - LOCAL AND OTHERWISE
//
/////////////////////////////////////////////////////////////////
plKey FindSceneObjectByName(const char* name, const char* ageName, char* statusStr, bool subString=false);
plKey FindObjectByName(const char* name, int type, const char* ageName, char* statusStr, bool subString=false);
plKey FindObjectByNameAndType(const char* name, const char* typeName, const char* ageName,
char* statusStr, bool subString=false);
void PrintStringF(void pfun(const char *),const char * fmt, ...);
PF_CONSOLE_GROUP( Avatar )
#ifndef LIMIT_CONSOLE_COMMANDS
PF_CONSOLE_SUBGROUP( Avatar, Spawn )
PF_CONSOLE_SUBGROUP( Avatar, Multistage )
PF_CONSOLE_SUBGROUP( Avatar, X ) // experimental stuff
PF_CONSOLE_SUBGROUP( Avatar, Climb )
PF_CONSOLE_SUBGROUP( Avatar, Turn ) // Turning config
PF_CONSOLE_SUBGROUP( Avatar, Physics )
PF_CONSOLE_SUBGROUP( Avatar, Warp )
PF_CONSOLE_SUBGROUP( Avatar, Anim ) // anim commands
PF_CONSOLE_SUBGROUP( Avatar, AG ) // animation graph stuff
PF_CONSOLE_SUBGROUP( Avatar, LOD )
#endif // LIMIT_CONSOLE_COMMANDS
#include "../plAvatar/plAnimStage.h"
plAvBrainHuman * GetMainAvatarBrain()
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
plAvBrainHuman *brain = plAvBrainHuman::ConvertNoRef(avatar->GetBrain(0));
if(brain)
return brain;
}
return nil;
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// THE COMMANDS
//
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//
// SPAWNING
//
/////////////////////////////////////////////////////////////////////////////////////////
#ifndef LIMIT_CONSOLE_COMMANDS
PF_CONSOLE_CMD( Avatar_Spawn, Show, "", "Print a list of spawn points.")
{
plAvatarMgr *mgr = plAvatarMgr::GetInstance();
int n = mgr->NumSpawnPoints();
for (int i = 0; i < n; i++)
{
const plSpawnModifier * spawn = mgr->GetSpawnPoint(i);
if(spawn)
{
PrintStringF(PrintString, "%d. %s", i, spawn->GetKey()->GetName());
}
}
}
PF_CONSOLE_CMD( Avatar_Spawn, Go, "int which", "Go a spawn point indicated by number.")
{
plAvatarMgr *mgr = plAvatarMgr::GetInstance();
int n = params[0];
int max = mgr->NumSpawnPoints();
if(n < max)
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar)
{
double fakeTime = 0.0f;
avatar->SpawnAt(n, fakeTime);
}
}
}
static int whichSpawn = 0;
PF_CONSOLE_CMD( Avatar_Spawn, next, "", "Go to the next spawn point in sequence.")
{
plAvatarMgr *mgr = plAvatarMgr::GetInstance();
int max = mgr->NumSpawnPoints();
whichSpawn = ++whichSpawn < max ? whichSpawn : 0;
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
PrintStringF(PrintString, "Spawning at point %d", whichSpawn);
double fakeTime = 0.0f;
avatar->SpawnAt(whichSpawn, fakeTime);
}
}
PF_CONSOLE_CMD( Avatar_Spawn, prev, "", "Go to the prev spawn point in sequence.")
{
plAvatarMgr *mgr = plAvatarMgr::GetInstance();
int max = mgr->NumSpawnPoints();
whichSpawn= --whichSpawn >= 0 ? whichSpawn: max-1;
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
PrintStringF(PrintString, "Spawning at point %d", whichSpawn);
double fakeTime = 0.0f;
avatar->SpawnAt(whichSpawn, fakeTime);
}
}
PF_CONSOLE_CMD( Avatar_Spawn, Respawn,"", "Moves the avatar back to the start point.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar)
{
avatar->Spawn(0);
}
}
PF_CONSOLE_CMD( Avatar_Spawn, SetSpawnOverride, "string spawnPointName", "Overrides the normal spawn point choice to be the object specified.")
{
plArmatureMod::SetSpawnPointOverride( (const char *)params[ 0 ] );
char str1[ 512 ];
sprintf( str1, "Spawn point override set to object %s", (const char *)params[ 0 ] );
PrintString( str1 );
}
PF_CONSOLE_CMD( Avatar_Spawn, DontPanic,"", "Toggles the Don't panic link flag.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar)
{
bool state = avatar->ToggleDontPanicLinkFlag();
char str1[256];
sprintf(str1, "DontPanic set to %s", state?"true":"false");
PrintString( str1 );
}
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// TURN TUNING
//
/////////////////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_CMD( Avatar_Turn, GetMaxTurn, "int walk", "Show the maximum turn speed in radians per second.")
{
plAvBrainHuman *brain = GetMainAvatarBrain();
float maxTurn = brain->GetMaxTurnSpeed((int)params[0] != 0);
PrintStringF(PrintString, "Avatar max turn speed is %f radians per second.", maxTurn);
}
PF_CONSOLE_CMD( Avatar_Turn, SetMaxTurn, "float maxTurn, int walk", "Set the maximum turn speed in radians per second.")
{
plAvBrainHuman *brain = GetMainAvatarBrain();
float newMaxTurn = params[0];
brain->SetMaxTurnSpeed(newMaxTurn, (int)params[1] != 0);
PrintStringF(PrintString, "Set the avatar max turn speed to %f radians per second.", newMaxTurn);
}
// TURN TIME
PF_CONSOLE_CMD( Avatar_Turn, GetTurnTime, "int walk", "Show the amount of time required to reach max turn speed.")
{
plAvBrainHuman *brain = GetMainAvatarBrain();
float turnTime = brain->GetTimeToMaxTurn((int)params[0] != 0);
PrintStringF(PrintString, "The amount of time required to reach max avatar turn speed is %f seconds.", turnTime);
}
PF_CONSOLE_CMD( Avatar_Turn, SetTurnTime, "float turnTime, int walk", "Set the amount of time required to reach max turn speed.")
{
plAvBrainHuman *brain = GetMainAvatarBrain();
float newTurnTime = params[0];
brain->SetTimeToMaxTurn(newTurnTime, (int)params[1] != 0);
PrintStringF(PrintString, "Set the amount of time required to reach max avatar turn speed to %f seconds.", newTurnTime);
}
// TURN TYPE
PF_CONSOLE_CMD( Avatar_Turn, GetTurnType, "int walk", "Show the amount of time required to reach max turn speed.")
{
plAvBrainHuman *brain = GetMainAvatarBrain();
int turnType = brain->GetTurnCurve((int)params[0] != 0);
PrintStringF(PrintString, "The avatar turn curve type is %d.", turnType);
}
PF_CONSOLE_CMD( Avatar_Turn, SetTurnType, "int turnType, int walk", "Set the turn acceleration curve type [0..2].")
{
plAvBrainHuman *brain = GetMainAvatarBrain();
int newCurveType = params[0];
brain->SetTurnCurve(plAvBrainHuman::TurnCurve(newCurveType), (int)params[1] != 0);
PrintStringF(PrintString, "Set turn curve to %d.", newCurveType);
}
PF_CONSOLE_CMD( Avatar_Turn, SetMouseTurnSensitivity, "float sensitivity", "Set how strong the mouse affects turning.")
{
plArmatureMod::SetMouseTurnSensitivity(params[0]);
PrintStringF(PrintString, "Set mouse sensitivity to %f", (float)params[0]);
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// MULTISTAGE
//
/////////////////////////////////////////////////////////////////////////////////////////
// MULTISTAGE.TRIGGER
PF_CONSOLE_CMD( Avatar_Multistage, Trigger, "string multiComp", "Triggers the named Multistage Animation component")
{
char str[256];
plKey key = FindObjectByNameAndType((const char*)params[0], "plMultistageBehMod", nil, str, true);
PrintString(str);
if (key)
{
plNotifyMsg *msg = TRACKED_NEW plNotifyMsg;
msg->fType = plNotifyMsg::kActivator;
msg->fState = 1; // Triggered
// Setup the event data in case this is a OneShot responder that needs it
plKey playerKey = plAvatarMgr::GetInstance()->GetLocalAvatar()->GetKey();
proPickedEventData *ed = TRACKED_NEW proPickedEventData;
ed->fPicker = playerKey;
ed->fPicked = key; // ???
msg->AddEvent(ed);
// Send it to the responder modifier
msg->AddReceiver(key);
plgDispatch::MsgSend(msg);
}
}
// MULTISTAGE.ADVANCE
PF_CONSOLE_CMD( Avatar_Multistage, Advance, "", "Advances the avatar's current multistage to the next stage.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar)
{
plKey avKey = avatar->GetKey();
plAvBrainGenericMsg *msg = TRACKED_NEW plAvBrainGenericMsg(nil, avKey, plAvBrainGenericMsg::kNextStage, 0, true, 0.5f);
msg->Send();
}
}
// MULTISTAGE.REGRESS
PF_CONSOLE_CMD( Avatar_Multistage, Regress, "", "Regresses the avatar's current multistage to the previous stage.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar)
{
plKey avKey = avatar->GetKey();
plAvBrainGenericMsg *msg = TRACKED_NEW plAvBrainGenericMsg(nil, avKey, plAvBrainGenericMsg::kPrevStage, 0, true, 0.5f);
msg->Send();
}
}
PF_CONSOLE_CMD( Avatar_Multistage, Mode, "string stage1, string stage2, string stage3", "make a simple multistage")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
const char *one = params[0];
const char *two = params[1];
const char *three = params[2];
PushSimpleMultiStage(avatar, one, two, three, true, true, plAGAnim::kBodyFull);
}
/////////////////////////////////////////////////////////////////////////////////////////
//
// MISCKELANYOUS
//
/////////////////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_CMD( Avatar, Debug, "", "Toggle the avatar debug display.")
{
static int toggle = 0;
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
toggle = toggle ? 0 : 1;
avatar->SetDebugState(toggle);
}
}
PF_CONSOLE_CMD( Avatar, DebugByID, "int PlayerID", "Show debug display for a specific avatar.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->FindAvatarByPlayerID((int)params[0]);
if (avatar)
{
avatar->SetDebugState(!avatar->GetDebugState());
}
}
PF_CONSOLE_CMD( Avatar, LogSmartSeek, "int enabled", "Enable/Disable smart seek logging (avatar.log)")
{
plAvTaskSeek::fLogProcess = ((int)params[0] == 1);
}
PF_CONSOLE_CMD( Avatar, PopBrain, "", "Remove the topmost brain from the avatar. Careful there, sport.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
avatar->PopBrain();
}
}
#include "../plScene/plRelevanceMgr.h"
PF_CONSOLE_CMD( Avatar,
MarkRelevanceRegion,
"string regionA, string regionB, int wantsUpdate",
"Mark whether avatars in regionA want updates on those on regionB" )
{
plRelevanceMgr *mgr = plRelevanceMgr::Instance();
char *regA = params[0];
char *regB = params[1];
mgr->MarkRegion(mgr->GetIndex(regA), mgr->GetIndex(regB), params[2]);
}
PF_CONSOLE_CMD( Avatar,
ToggleRelevanceRegions,
"",
"Enable/Disable all relevance regions" )
{
plRelevanceMgr *mgr = plRelevanceMgr::Instance();
mgr->SetEnabled(!mgr->GetEnabled());
char buff[256];
sprintf(buff, "All relevance regions are now %s", (mgr->GetEnabled() ? "ENABLED" : "DISABLED"));
PrintString(buff);
}
PF_CONSOLE_CMD( Avatar, SeekPoint, "string seekpoint", "Move to the given seekpoint.")
{
char *spName = params[0];
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
char buff[256];
plKey seekKey = FindSceneObjectByName(spName, nil, buff);
plSeekPointMod *mod = plAvatarMgr::GetInstance()->FindSeekPoint(spName);
if(mod)
{
plKey seekKey = mod->GetKey();
plSeekPointMod *seekMod = (plSeekPointMod *)seekKey->GetObjectPtr();
plSceneObject *seekTarget = seekMod->GetTarget(0);
plKey targetKey = seekTarget->GetKey();
plKey avKey = avatar->GetKey();
hsScalar unused = 0.0f;
plAvSeekMsg *msg = TRACKED_NEW plAvSeekMsg(nil, avKey, targetKey, unused, false);
plgDispatch::MsgSend(msg);
}
}
}
PF_CONSOLE_CMD( Avatar, ShowLocations, "", "Show player positions/orientations" )
{
hsBool curVal = plNetClientApp::GetInstance()->GetFlagsBit(plNetClientApp::kShowAvatars);
plNetClientApp::GetInstance()->SetFlagsBit(plNetClientApp::kShowAvatars, !curVal);
}
PF_CONSOLE_CMD( Avatar,
SetFootEffect,
"int group",
"Force the avatar to use certain footstep effects" )
{
const plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avMod)
{
plArmatureEffectStateMsg *msg = TRACKED_NEW plArmatureEffectStateMsg();
msg->AddReceiver(avMod->GetArmatureEffects()->GetKey());
msg->fSurface = (int)params[0];
plgDispatch::MsgSend(msg);
}
}
PF_CONSOLE_CMD( Avatar, SetStealthMode, "int mode", "Set the stealth mode of your avatar.")
{
const plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avMod)
{
int mode=params[0];
plKey avKey=avMod->GetTarget(0)->GetKey();
int level = mode==plAvatarStealthModeMsg::kStealthVisible ? 0 : 1;
// send msg to make myself invisible locally
plAvatarStealthModeMsg *msg = TRACKED_NEW plAvatarStealthModeMsg();
msg->SetSender(avKey);
msg->fMode = mode;
msg->fLevel = level;
plgDispatch::MsgSend(msg);
// send net msg to other players to synch them up
// the msg will go to their NetClientMgr who will decide whether they see
// our avatar as total or semi-invisible based on the invis level.
plCCRInvisibleMsg *invisMsg = TRACKED_NEW plCCRInvisibleMsg; // ctor sets flags and receiver
invisMsg->fInvisLevel=level;
invisMsg->fAvKey=avKey;
invisMsg->Send();
}
}
PF_CONSOLE_CMD( Avatar, SortFaces, "", "Toggle sorting of polys on the avatar" )
{
const plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
const plSceneObject *so = avMod->GetClothingSO(0);
plInstanceDrawInterface *idi = plInstanceDrawInterface::ConvertNoRef(const_cast<plDrawInterface*>(so->GetDrawInterface()));
plDrawableSpans *drawable = idi->GetInstanceDrawable();
drawable->SetNativeProperty(plDrawable::kPropSortFaces, !drawable->GetNativeProperty(plDrawable::kPropSortFaces));
}
#endif // LIMIT_CONSOLE_COMMANDS
PF_CONSOLE_CMD( Avatar, SetMouseTurnSensitivity, "float sensitivity", "Set how strong the mouse affects turning.")
{
plArmatureMod::SetMouseTurnSensitivity(params[0]);
PrintStringF(PrintString, "Set mouse sensitivity to %f", (float)params[0]);
}
PF_CONSOLE_CMD( Avatar, ClickToTurn, "bool b", "Set click-to-turn functionality.")
{
bool b = params[0];
plArmatureMod::fClickToTurn = b;
}
PF_CONSOLE_CMD( Avatar, FakeLinkToObj, "string objName", "Pseudo-Link the avatar to the specified object's location")
{
char *spName = params[0];
char buff[256];
plKey seekKey = FindSceneObjectByName(spName, nil, buff);
if (!seekKey)
{
PrintString("Can't find object with that name, fake link failed.");
return;
}
plPseudoLinkEffectMsg* msg = TRACKED_NEW plPseudoLinkEffectMsg;
msg->fAvatarKey = plNetClientMgr::GetInstance()->GetLocalPlayerKey();
msg->fLinkObjKey = seekKey;
plgDispatch::MsgSend(msg);
}
#ifndef LIMIT_CONSOLE_COMMANDS
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// PHYSICS
//
///////////////////////////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_CMD( Avatar_Physics, TogglePhysical, "", "Disable/enable physics on the avatar.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
plControlEventMsg* pMsg = TRACKED_NEW plControlEventMsg;
pMsg->SetControlActivated(true);
pMsg->SetControlCode(B_CONTROL_TOGGLE_PHYSICAL);
avatar->MsgReceive(pMsg);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Animation
//
///////////////////////////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_CMD( Avatar_Anim, BlendAnim, "string Animation, float blendFactor", "Blend the given animation with the current animation.")
{
char *animationName = params[0];
float blendFactor = params[1];
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar && animationName)
{
plAGAnim * anim = plAGAnim::FindAnim(animationName);
if(anim)
{
plAGAnimInstance * inst = avatar->AttachAnimationBlended(animationName, blendFactor);
inst->SetLoop(true);
} else
PrintString("BlendAnim: Couldn't find animation.");
}
}
PF_CONSOLE_CMD( Avatar_Anim, BlendAnimPri, "string Animation, float blendFactor, int priority", "Blend animation using priority.")
{
char *animationName = params[0];
float blendFactor = params[1];
int priority = params[2];
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar && animationName)
{
plAGAnim * anim = plAGAnim::FindAnim(animationName);
if(anim)
{
plAGAnimInstance * inst = avatar->AttachAnimationBlended(animationName, blendFactor, priority);
inst->SetLoop(true);
} else
PrintString("BlendAnim: Couldn't find animation.");
}
}
PF_CONSOLE_CMD( Avatar_Anim, PlaySimpleAnim, "string AvatarName, string Animation", "Play a simple (root not animated) one time animation on the avatar")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->FindAvatarByModelName(params[0]);
if (avatar)
avatar->PlaySimpleAnim(params[1]);
}
PF_CONSOLE_CMD( Avatar_Anim, DetachAnim, "string Animation", "Remove the given animation from the avatar.")
{
char *animationName = params[0];
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar && animationName)
{
plAGAnimInstance * instance = avatar->FindAnimInstance(animationName);
if(instance)
avatar->DetachAnimation(instance);
else
PrintString("DetachAnim: Couldn't find animation on avatar.");
}
}
PF_CONSOLE_CMD( Avatar_Anim, SetBlend, "string Animation, float blend", "Set the blend of the given animation.")
{
char *animationName = params[0];
float blend = params[1];
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if (avatar && animationName)
{
plAGAnimInstance *anim = avatar->FindAnimInstance(animationName);
if(anim)
anim->SetBlend(blend);
else
PrintString("SetBlend: Couldn't find animation.");
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// LOD
//
///////////////////////////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_CMD( Avatar_LOD, SetLOD, "int lod", "Show only the selected LOD.")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avatar)
{
plArmatureLODMod *lodder = plArmatureLODMod::ConvertNoRef(avatar);
if(lodder)
{
int lod = params[0];
lodder->SetLOD(lod);
} else {
PrintString("SetLOD: found avatar, but it doesn't support LOD.");
}
} else {
PrintString("SetLOD: couldn't find avatar with that name.");
}
}
PF_CONSOLE_CMD( Avatar_LOD, LimitLOD, "int newLOD", "Zero is (always) highest detail; 2 is (currently) lowest." )
{
int newLOD = params[0];
if(newLOD >= 0 && newLOD <= 2)
plArmatureLODMod::fMinLOD = newLOD;
}
PF_CONSOLE_CMD( Avatar_LOD, SetLODDistance, "float newDist", "Set Distance for switching Avatar LOD" )
{
plArmatureLODMod::fLODDistance = float(params[0]);
}
PF_CONSOLE_CMD( Avatar_LOD, GetLODDistance, "", "Get Distance for switching Avatar LOD" )
{
char buffer[256];
sprintf(buffer, "Lod Distance = %f", plArmatureLODMod::fLODDistance);
PrintString(buffer);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// CLIMBING
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "../plAvatar/plAvBrainClimb.h"
PF_CONSOLE_CMD( Avatar_Climb, Start, "string direction", "Specify initial mount direction: up, down, left, right")
{
plArmatureMod *avMod = const_cast<plArmatureMod *>(plAvatarMgr::GetInstance()->GetLocalAvatar());
if(avMod)
{
const char *dirStr = params[0];
plAvBrainClimb::Mode mode;
if(stricmp(dirStr, "up") == 0)
mode = plAvBrainClimb::kMountingUp;
else if(stricmp(dirStr, "down") == 0)
mode = plAvBrainClimb::kMountingDown;
else if(stricmp(dirStr, "left") == 0)
mode = plAvBrainClimb::kMountingLeft;
else if(stricmp(dirStr, "right") == 0)
mode = plAvBrainClimb::kMountingRight;
plAvBrainClimb *brain = TRACKED_NEW plAvBrainClimb(mode);
avMod->PushBrain(brain);
}
}
PF_CONSOLE_CMD( Avatar_Climb, EnableDismount, "string direction", "Let the avatar dismount in the specified direction.")
{
plArmatureMod *avMod = const_cast<plArmatureMod *>(plAvatarMgr::GetInstance()->GetLocalAvatar());
if(avMod)
{
plKey mgr = plAvatarMgr::GetInstance()->GetKey();
plKey avKey = avMod->GetKey();
const char *dirStr = params[0];
plClimbMsg::Direction dir;
if(stricmp(dirStr, "up") == 0)
dir = plClimbMsg::kUp;
else if(stricmp(dirStr, "down") == 0)
dir = plClimbMsg::kDown;
else if(stricmp(dirStr, "left") == 0)
dir = plClimbMsg::kLeft;
else if(stricmp(dirStr, "right") == 0)
dir = plClimbMsg::kRight;
plClimbMsg *msg = TRACKED_NEW plClimbMsg(mgr, avKey, plClimbMsg::kEnableDismount, dir, true);
msg->Send();
}
}
PF_CONSOLE_CMD( Avatar_Climb, EnableClimb, "string direction, int onOff", "Allow or forbid climbing in the given direction.")
{
plArmatureMod *avMod = const_cast<plArmatureMod *>(plAvatarMgr::GetInstance()->GetLocalAvatar());
if(avMod)
{
plKey mgr = plAvatarMgr::GetInstance()->GetKey();
plKey avKey = avMod->GetKey();
const char *dirStr = params[0];
plClimbMsg::Direction dir;
if(stricmp(dirStr, "up") == 0)
dir = plClimbMsg::kUp;
else if(stricmp(dirStr, "down") == 0)
dir = plClimbMsg::kDown;
else if(stricmp(dirStr, "left") == 0)
dir = plClimbMsg::kLeft;
else if(stricmp(dirStr, "right") == 0)
dir = plClimbMsg::kRight;
hsBool enable = static_cast<int>(params[1]) ? true : false;
plClimbMsg *msg = TRACKED_NEW plClimbMsg(mgr, avKey, plClimbMsg::kEnableClimb, dir, enable);
msg->Send();
}
}
PF_CONSOLE_CMD( Avatar_Climb, Release, "", "")
{
plArmatureMod *avMod = const_cast<plArmatureMod *>(plAvatarMgr::GetInstance()->GetLocalAvatar());
if(avMod)
{
plKey mgr = plAvatarMgr::GetInstance()->GetKey();
plKey avKey = avMod->GetKey();
plClimbMsg *msg = TRACKED_NEW plClimbMsg(mgr, avKey, plClimbMsg::kRelease);
msg->Send();
}
}
PF_CONSOLE_CMD( Avatar_Climb, FallOff, "", "")
{
plArmatureMod *avMod = plAvatarMgr::GetInstance()->GetLocalAvatar();
if(avMod)
{
plKey mgr = plAvatarMgr::GetInstance()->GetKey();
plKey avKey = avMod->GetKey();
plClimbMsg *msg = TRACKED_NEW plClimbMsg(mgr, avKey, plClimbMsg::kFallOff);
msg->Send();
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// SWIMMING
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_SUBGROUP( Avatar, Swim )
PF_CONSOLE_CMD( Avatar_Swim, Start, "", "")
{
plArmatureMod *avMod = const_cast<plArmatureMod*>(plAvatarMgr::GetInstance()->GetLocalAvatar());
if(avMod)
{
plAvBrainSwim * brayne = TRACKED_NEW plAvBrainSwim();
avMod->PushBrain(brayne);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// WARP
//
///////////////////////////////////////////////////////////////////////////////////////////////////
// void WarpPlayerToAnother(hsBool iMove, UInt32 remoteID)
PF_CONSOLE_CMD( Avatar_Warp, WarpToPlayer, "int PlayerID", "Warp our player to the same position as another player.")
{
plAvatarMgr::WarpPlayerToAnother(true, (int)params[0]);
}
PF_CONSOLE_CMD( Avatar_Warp, WarpPlayerHere, "int PlayerID", "Warp another player to the same position as us.")
{
plAvatarMgr::WarpPlayerToAnother(false, (int)params[0]);
}
PF_CONSOLE_CMD( Avatar_Warp, WarpToXYZ, "float x, float y, float z", "Warp our avatar to the given location.")
{
plAvatarMgr::WarpPlayerToXYZ((float)params[0], (float)params[1], (float)params[2]);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// AG (Animation Graph)
//
///////////////////////////////////////////////////////////////////////////////////////////////////
#include "hsTimer.h"
PF_CONSOLE_CMD( Avatar_AG, DumpFull, "", "print out the animation graph for the avatar")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
double time = hsTimer::GetSysSeconds();
avatar->DumpAniGraph(nil, false, time);
}
PF_CONSOLE_CMD( Avatar_AG, DumpFullOptimized, "", "print out the optimized animation graph for the avatar")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
double time = hsTimer::GetSysSeconds();
avatar->DumpAniGraph(nil, true, time);
}
PF_CONSOLE_CMD( Avatar_AG, DumpSingle, "string boneName", "print out the animation graph for the given (avatar) bone")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
double time = hsTimer::GetSysSeconds();
const char *bone = params[0];
avatar->DumpAniGraph(bone, false, time);
}
PF_CONSOLE_CMD( Avatar_AG, DumpSingleOptimized, "string boneName", "print out the optimized animatoin graph for the given (avatar) bone")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
double time = hsTimer::GetSysSeconds();
const char *bone = params[0];
avatar->DumpAniGraph(bone, true, time);
}
#endif // LIMIT_CONSOLE_COMMANDS

View File

@ -0,0 +1,60 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// CCR Console Commands and Groups //
// These console commands are meant for use by customer care reps. //
// Eventually the functionality defined here will be accessed through a GUI//
// //
//////////////////////////////////////////////////////////////////////////////
//
// Only calls to the CCRMgr interface are allowed here
// See me if you need to include any other files...
//
#include "pfConsoleCmd.h"
#include "pfConsole.h"
#include "../pfCCR/plCCRMgr.h"
#include "../plNetClient/plNetClientMgr.h"
//// This is here so Microsoft VC won't decide to "optimize" this file out
// YOU ALSO NEED TO CALL THIS FXN
void pfConsoleCmdGroup::DummyCCR( void )
{
}
void PrintStringF(void pfun(const char *),const char * fmt, ...);
/////////////////////////////////////////////////////////////////
//
// Please see pfConsoleCommands.cpp for detailed instructions on
// how to add console commands.
//
/////////////////////////////////////////////////////////////////
#define PF_SANITY_CHECK( cond, msg ) { if( !( cond ) ) { PrintString( msg ); return; } }

View File

@ -0,0 +1,149 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsole Header //
// //
// 9.21.2001 mcn - Added pfLogDisplays. These are classes that represent //
// a scrolling buffer, much like the console, for on- //
// screen display of error logs and the such. Currently //
// managed by the console, but hopefully once we have //
// a general manager for dialogs/menus (debug or //
// otherwise), that manager will take the displays over. //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _pfConsole_h
#define _pfConsole_h
#include "hsTypes.h"
#include "../pnKeyedObject/hsKeyedObject.h"
class plPipeline;
//// Class Definition ////////////////////////////////////////////////////////
class pfConsoleEngine;
class plKeyEventMsg;
class pfConsoleInputInterface;
class pfConsole : public hsKeyedObject
{
friend class pfConsoleInputInterface;
protected:
enum Konstants
{
kNumHistoryItems = 16,
kModeHidden = 0,
kModeSingleLine = 1,
kModeFull = 2,
kEffectDivisions = 1000,
kMaxCharsWide = 80,
kHelpDelay = 32,
kCursorBlinkRate = 16,
kMsgHintTimeout = 64,
kWorkingLineSize = 256
};
UInt32 fNumDisplayLines;
Int32 fEffectCounter;
float fLastTime;
UInt32 fHelpTimer;
char fLastHelpMsg[ kWorkingLineSize ];
UInt8 fMode; // 0 - invisible, 1 - single line, 2 - full
hsBool fInited, fHelpMode, fPythonMode, fPythonFirstTime, fFXEnabled;
UInt32 fPythonMultiLines;
short fCursorTicks;
UInt32 fMsgTimeoutTimer;
char fHistory[ kNumHistoryItems ][ kMaxCharsWide ];
UInt32 fHistoryCursor, fHistoryRecallCursor;
char *fDisplayBuffer;
char fWorkingLine[ kWorkingLineSize ];
UInt32 fWorkingCursor;
pfConsoleInputInterface *fInputInterface;
pfConsoleEngine *fEngine;
void IHandleKey( plKeyEventMsg *msg );
char IKeyEventToChar( plKeyEventMsg *msg );
static UInt32 fConsoleTextColor;
static pfConsole *fTheConsole;
static void _cdecl IAddLineCallback( const char *string );
static plPipeline *fPipeline;
void IAddLine( const char *string, short leftMargin = 0 );
void IAddParagraph( const char *string, short margin = 0 );
void IClear( void );
void ISetMode( UInt8 mode );
void IEnableFX( hsBool e ) { fFXEnabled = e; }
hsBool IFXEnabled( void ) { return fFXEnabled; }
void IPrintSomeHelp( void );
void IUpdateTooltip( void );
public:
pfConsole();
~pfConsole();
CLASSNAME_REGISTER( pfConsole );
GETINTERFACE_ANY( pfConsole, plReceiver );
static pfConsole * GetInstance ();
virtual hsBool MsgReceive( plMessage *msg );
void Init( pfConsoleEngine *engine );
void Draw( plPipeline *p );
static void AddLine( const char *string ) { fTheConsole->IAddParagraph( string ); }
static void AddLineF(const char * fmt, ...);
static void Clear( void ) { fTheConsole->IClear(); }
static void Hide( void ) { fTheConsole->ISetMode(kModeHidden); }
static void EnableEffects( hsBool enable ) { fTheConsole->IEnableFX( enable ); }
static hsBool AreEffectsEnabled( void ) { return fTheConsole->IFXEnabled(); }
static void SetTextColor( UInt32 color ) { fConsoleTextColor = color; }
static UInt32 GetTextColor() { return fConsoleTextColor; }
static void SetPipeline( plPipeline *pipe ) { fPipeline = pipe; }
static plPipeline *GetPipeline( void ) { return fPipeline; }
static void RunCommandAsync (const char cmd[]);
};
#endif //_pfConsole_h

View File

@ -0,0 +1,657 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleCmd Functions //
// //
//////////////////////////////////////////////////////////////////////////////
#include "pfConsoleCmd.h"
#include "hsUtils.h"
//////////////////////////////////////////////////////////////////////////////
//// pfConsoleCmdGroup Stuff /////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
pfConsoleCmdGroup *pfConsoleCmdGroup::fBaseCmdGroup = nil;
UInt32 pfConsoleCmdGroup::fBaseCmdGroupRef = 0;
//// Constructor & Destructor ////////////////////////////////////////////////
pfConsoleCmdGroup::pfConsoleCmdGroup( char *name, char *parent )
{
Dummy();
DummyJunior();
DummyNet();
DummyAvatar();
DummyCCR();
fNext = nil;
fPrevPtr = nil;
fCommands = nil;
fSubGroups = nil;
if( name == nil )
{
/// Create base
hsStrncpy( fName, "base", sizeof( fName ) );
fParentGroup = nil;
}
else
{
pfConsoleCmdGroup *group = GetBaseGroup();
if( parent != nil && parent[ 0 ] != 0 )
{
group = group->FindSubGroupRecurse( parent );
hsAssert( group != nil, "Trying to register group under nonexistant group!" );
}
hsStrncpy( fName, name, sizeof( fName ) );
group->AddSubGroup( this );
fParentGroup = group;
}
}
pfConsoleCmdGroup::~pfConsoleCmdGroup()
{
if( this != fBaseCmdGroup )
{
Unlink();
DecBaseCmdGroupRef();
}
}
//// GetBaseGroup ////////////////////////////////////////////////////////////
pfConsoleCmdGroup *pfConsoleCmdGroup::GetBaseGroup( void )
{
if( fBaseCmdGroup == nil )
{
/// Initialize base group
fBaseCmdGroup = TRACKED_NEW pfConsoleCmdGroup( nil, nil );
}
return fBaseCmdGroup;
}
//// DecBaseCmdGroupRef //////////////////////////////////////////////////////
void pfConsoleCmdGroup::DecBaseCmdGroupRef( void )
{
fBaseCmdGroupRef--;
if( fBaseCmdGroupRef == 0 )
{
delete fBaseCmdGroup;
fBaseCmdGroup = nil;
}
}
//// Add Functions ///////////////////////////////////////////////////////////
void pfConsoleCmdGroup::AddCommand( pfConsoleCmd *cmd )
{
cmd->Link( &fCommands );
fBaseCmdGroupRef++;
}
void pfConsoleCmdGroup::AddSubGroup( pfConsoleCmdGroup *group )
{
group->Link( &fSubGroups );
fBaseCmdGroupRef++;
}
//// FindCommand /////////////////////////////////////////////////////////////
// No longer recursive.
pfConsoleCmd *pfConsoleCmdGroup::FindCommand( char *name )
{
pfConsoleCmd *cmd;
hsAssert( name != nil, "nil name passed to FindCommand()" );
/// Only search locally
for( cmd = fCommands; cmd != nil; cmd = cmd->GetNext() )
{
if( strcmp( cmd->GetName(), name ) == 0 )
return cmd;
}
return nil;
}
//// FindNestedPartialCommand ////////////////////////////////////////////////
// Okay. YAFF. This one searches through the group and its children looking
// for a partial command based on the string given. The counter determines
// how many matches it skips before returning a match. (That way you can
// cycle through matches by sending 1 + the last counter every time).
pfConsoleCmd *pfConsoleCmdGroup::FindNestedPartialCommand( char *name, UInt32 *counter )
{
pfConsoleCmd *cmd;
pfConsoleCmdGroup *group;
hsAssert( name != nil, "nil name passed to FindNestedPartialCommand()" );
hsAssert( counter != nil, "nil counter passed to FindNestedPartialCommand()" );
// Try us
for( cmd = fCommands; cmd != nil; cmd = cmd->GetNext() )
{
if( _strnicmp( cmd->GetName(), name, strlen( name ) ) == 0 )
{
if( *counter == 0 )
return cmd;
(*counter)--;
}
}
// Try children
for( group = fSubGroups; group != nil; group = group->GetNext() )
{
cmd = group->FindNestedPartialCommand( name, counter );
if( cmd != nil )
return cmd;
}
return nil;
}
//// FindSubGroup ////////////////////////////////////////////////////////////
pfConsoleCmdGroup *pfConsoleCmdGroup::FindSubGroup( char *name )
{
pfConsoleCmdGroup *group;
hsAssert( name != nil, "nil name passed to FindSubGroup()" );
/// Only search locally
for( group = fSubGroups; group != nil; group = group->GetNext() )
{
if( strcmp( group->GetName(), name ) == 0 )
return group;
}
return nil;
}
//// FindSubGroupRecurse /////////////////////////////////////////////////////
// Resurces through a string, finding the final subgroup that the string
// represents. Parses with spaces, _ or . as the separators. Copies string.
pfConsoleCmdGroup *pfConsoleCmdGroup::FindSubGroupRecurse( const char *name )
{
char *ptr, *string;
pfConsoleCmdGroup *group;
static char seps[] = " ._";
string = TRACKED_NEW char[ strlen( name ) + 1 ];
hsAssert( string != nil, "Cannot allocate string in FindSubGroupRecurse()" );
strcpy( string, name );
/// Scan for subgroups
group = pfConsoleCmdGroup::GetBaseGroup();
ptr = strtok( string, seps );
while( ptr != nil )
{
// Take this token and check to see if it's a group
group = group->FindSubGroup( ptr );
hsAssert( group != nil, "Invalid group name to FindSubGroupRecurse()" );
ptr = strtok( nil, seps );
}
delete [] string;
return group;
}
//// FindCommandNoCase ///////////////////////////////////////////////////////
// Case-insensitive version of FindCommand.
pfConsoleCmd *pfConsoleCmdGroup::FindCommandNoCase( char *name, UInt8 flags, pfConsoleCmd *start )
{
pfConsoleCmd *cmd;
hsAssert( name != nil, "nil name passed to FindCommandNoCase()" );
/// Only search locally
if( start == nil )
start = fCommands;
else
start = start->GetNext();
if( flags & kFindPartial )
{
for( cmd = start; cmd != nil; cmd = cmd->GetNext() )
{
if( _strnicmp( cmd->GetName(), name, strlen( name ) ) == 0 )
return cmd;
}
}
else
{
for( cmd = start; cmd != nil; cmd = cmd->GetNext() )
{
if( stricmp( cmd->GetName(), name ) == 0 )
return cmd;
}
}
return nil;
}
//// FindSubGroupNoCase //////////////////////////////////////////////////////
pfConsoleCmdGroup *pfConsoleCmdGroup::FindSubGroupNoCase( char *name, UInt8 flags, pfConsoleCmdGroup *start )
{
pfConsoleCmdGroup *group;
hsAssert( name != nil, "nil name passed to FindSubGroupNoCase()" );
/// Only search locally
if( start == nil )
start = fSubGroups;
else
start = start->GetNext();
if( flags & kFindPartial )
{
for( group = start; group != nil; group = group->GetNext() )
{
if( _strnicmp( group->GetName(), name, strlen( name ) ) == 0 )
return group;
}
}
else
{
for( group = start; group != nil; group = group->GetNext() )
{
if( stricmp( group->GetName(), name ) == 0 )
return group;
}
}
return nil;
}
//// Link & Unlink ///////////////////////////////////////////////////////////
void pfConsoleCmdGroup::Link( pfConsoleCmdGroup **prevPtr )
{
hsAssert( fNext == nil && fPrevPtr == nil, "Trying to link console group that's already linked!" );
fNext = *prevPtr;
if( *prevPtr )
(*prevPtr)->fPrevPtr = &fNext;
fPrevPtr = prevPtr;
*fPrevPtr = this;
}
void pfConsoleCmdGroup::Unlink( void )
{
hsAssert( fNext != nil || fPrevPtr != nil, "Trying to unlink console group that isn't linked!" );
if( fNext )
fNext->fPrevPtr = fPrevPtr;
*fPrevPtr = fNext;
}
int pfConsoleCmdGroup::IterateCommands(pfConsoleCmdIterator* t, int depth)
{
pfConsoleCmd *cmd;
cmd = this->GetFirstCommand();
while(cmd)
{
t->ProcessCmd(cmd,depth);
cmd = cmd->GetNext();
}
pfConsoleCmdGroup *grp;
grp = this->GetFirstSubGroup();
while(grp)
{
if(t->ProcessGroup(grp, depth))
grp->IterateCommands(t, depth+1);
grp = grp->GetNext();
}
return 0;
}
//////////////////////////////////////////////////////////////////////////////
//// pfConsoleCmd Functions //////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
char pfConsoleCmd::fSigTypes[ kNumTypes ][ 8 ] = { "int", "float", "bool", "string", "char", "void", "..." };
pfConsoleCmd::pfConsoleCmd( char *group, char *name, char *paramList, char *help,
pfConsoleCmdPtr func, hsBool localOnly )
{
fNext = nil;
fPrevPtr = nil;
fFunction = func;
fLocalOnly = localOnly;
hsStrncpy( fName, name, sizeof( fName ) );
fHelpString = help;
ICreateSignature( paramList );
Register( group, name );
}
pfConsoleCmd::~pfConsoleCmd()
{
int i;
for( i = 0; i < fSigLabels.GetCount(); i++ )
{
if( fSigLabels[ i ] != nil )
delete [] fSigLabels[ i ];
}
Unregister();
fSignature.Reset();
fSigLabels.Reset();
}
//// ICreateSignature ////////////////////////////////////////////////////////
// Creates the signature and sig labels based on the given string.
void pfConsoleCmd::ICreateSignature( char *paramList )
{
static char seps[] = " :-";
char params[ 256 ];
char *ptr, *nextPtr, *tok, *tok2;
int i;
/// Simple check
if( paramList == nil )
{
fSignature.Push( kAny );
fSigLabels.Push( (char *)nil );
return;
}
/// So we can do stuff to it
hsAssert( strlen( paramList ) < sizeof( params ), "Make the (#*$& params string larger!" );
hsStrcpy( params, paramList );
fSignature.Empty();
fSigLabels.Empty();
/// Loop through all the types given in the list
ptr = params;
do
{
/// Find break
nextPtr = strchr( ptr, ',' );
if( nextPtr != nil )
{
*nextPtr = 0;
nextPtr++;
}
/// Do this param
tok = strtok( ptr, seps );
if( tok == nil && ptr == params )
break;
hsAssert( tok != nil, "Bad parameter list for console command!" );
tok2 = strtok( nil, seps );
if( tok2 != nil )
{
// Type and label: assume label second
fSigLabels.Push( hsStrcpy( tok2 ) );
}
else
fSigLabels.Push( (char *)nil );
// Find type
for( i = 0; i < kNumTypes; i++ )
{
if( strcmp( fSigTypes[ i ], tok ) == 0 )
{
fSignature.Push( (UInt8)i );
break;
}
}
hsAssert( i < kNumTypes, "Bad parameter type in console command parameter list!" );
} while( ( ptr = nextPtr ) != nil );
}
//// Register ////////////////////////////////////////////////////////////////
// Finds the group this command should be in and registers it with that
// group.
void pfConsoleCmd::Register( char *group, char *name )
{
pfConsoleCmdGroup *g;
if( group == nil || group[ 0 ] == 0 )
{
g = pfConsoleCmdGroup::GetBaseGroup();
g->AddCommand( this );
}
else
{
g = pfConsoleCmdGroup::FindSubGroupRecurse( group );
hsAssert( g != nil, "Trying to register command under nonexistant group!" );
g->AddCommand( this );
}
fParentGroup = g;
}
//// Unregister //////////////////////////////////////////////////////////////
void pfConsoleCmd::Unregister( void )
{
Unlink();
pfConsoleCmdGroup::DecBaseCmdGroupRef();
}
//// Execute /////////////////////////////////////////////////////////////////
// Run da thing!
void pfConsoleCmd::Execute( Int32 numParams, pfConsoleCmdParam *params, void (*PrintFn)( const char * ) )
{
fFunction( numParams, params, PrintFn );
}
//// Link & Unlink ///////////////////////////////////////////////////////////
void pfConsoleCmd::Link( pfConsoleCmd **prevPtr )
{
hsAssert( fNext == nil && fPrevPtr == nil, "Trying to link console command that's already linked!" );
fNext = *prevPtr;
if( *prevPtr )
(*prevPtr)->fPrevPtr = &fNext;
fPrevPtr = prevPtr;
*fPrevPtr = this;
}
void pfConsoleCmd::Unlink( void )
{
hsAssert( fNext != nil || fPrevPtr != nil, "Trying to unlink console command that isn't linked!" );
if( fNext )
fNext->fPrevPtr = fPrevPtr;
*fPrevPtr = fNext;
}
//// GetSigEntry /////////////////////////////////////////////////////////////
UInt8 pfConsoleCmd::GetSigEntry( UInt8 i )
{
if( fSignature.GetCount() == 0 )
return kNone;
if( i < fSignature.GetCount() )
{
if( fSignature[ i ] == kEtc )
return kAny;
return fSignature[ i ];
}
if( fSignature[ fSignature.GetCount() - 1 ] == kEtc )
return kAny;
return kNone;
}
//// GetSignature ////////////////////////////////////////////////////////////
// Gets the signature of the command as a string. Format is:
// name [ type param [, type param ... ] ]
// WARNING: uses a static buffer, so don't rely on the contents if you call
// it more than once! (You shouldn't need to, though)
const char *pfConsoleCmd::GetSignature( void )
{
static char string[ 256 ];
int i;
char pStr[ 128 ];
strcpy( string, fName );
for( i = 0; i < fSignature.GetCount(); i++ )
{
if( fSigLabels[ i ] == nil )
sprintf( pStr, "%s", fSigTypes[ fSignature[ i ] ] );
else
sprintf( pStr, "%s %s", fSigTypes[ fSignature[ i ] ], fSigLabels[ i ] );
hsAssert( strlen( string ) + strlen( pStr ) + 2 < sizeof( string ), "Not enough room for signature string" );
strcat( string, ( i > 0 ) ? ", " : " " );
strcat( string, pStr );
}
return string;
}
//////////////////////////////////////////////////////////////////////////////
//// pfConsoleCmdParam Functions /////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//// Conversion Functions ////////////////////////////////////////////////////
const int & pfConsoleCmdParam::IToInt( void ) const
{
hsAssert( fType == kInt || fType == kAny, "Trying to use a non-int parameter as an int!" );
static int i;
if( fType == kAny )
{
hsAssert( fValue.s != nil, "Weird parameter during conversion" );
i = atoi( fValue.s );
return i;
}
return fValue.i;
}
const float & pfConsoleCmdParam::IToFloat( void ) const
{
hsAssert( fType == kFloat || fType == kAny, "Trying to use a non-float parameter as a float!" );
static float f;
if( fType == kAny )
{
hsAssert( fValue.s != nil, "Weird parameter during conversion" );
f = (float)atof( fValue.s );
return f;
}
return fValue.f;
}
const bool & pfConsoleCmdParam::IToBool( void ) const
{
hsAssert( fType == kBool || fType == kAny, "Trying to use a non-bool parameter as a bool!" );
static bool b;
if( fType == kAny )
{
hsAssert( fValue.s != nil, "Weird parameter during conversion" );
if( atoi( fValue.s ) > 0 || stricmp( fValue.s, "true" ) == 0 )
b = true;
else
b = false;
return b;
}
return fValue.b;
}
const pfConsoleCmdParam::CharPtr & pfConsoleCmdParam::IToString( void ) const
{
hsAssert( fType == kString || fType == kAny, "Trying to use a non-string parameter as a string!" );
return fValue.s;
}
const char & pfConsoleCmdParam::IToChar( void ) const
{
hsAssert( fType == kChar || fType == kAny, "Trying to use a non-char parameter as a char!" );
static char c;
if( fType == kAny )
{
hsAssert( fValue.s != nil, "Weird parameter during conversion" );
c = fValue.s[ 0 ];
return c;
}
return fValue.c;
}

View File

@ -0,0 +1,272 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleCmd Header //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _pfConsoleCmd_h
#define _pfConsoleCmd_h
#include "hsTypes.h"
#include "hsBiExpander.h"
//// pfConsoleCmdGroup Class Definition //////////////////////////////////////
class pfConsoleCmd;
class pfConsoleCmdIterator;
class pfConsoleCmdGroup
{
protected:
static pfConsoleCmdGroup *fBaseCmdGroup;
static UInt32 fBaseCmdGroupRef;
char fName[ 128 ];
pfConsoleCmdGroup *fNext;
pfConsoleCmdGroup **fPrevPtr;
pfConsoleCmdGroup *fSubGroups;
pfConsoleCmd *fCommands;
pfConsoleCmdGroup *fParentGroup;
public:
enum FindFlags {
kFindPartial = 0x01
};
pfConsoleCmdGroup( char *name, char *parent );
~pfConsoleCmdGroup();
void AddCommand( pfConsoleCmd *cmd );
void AddSubGroup( pfConsoleCmdGroup *group );
void Link( pfConsoleCmdGroup **prevPtr );
void Unlink( void );
pfConsoleCmdGroup *GetNext( void ) { return fNext; }
char *GetName( void ) { return fName; }
pfConsoleCmdGroup *GetParent( void ) { return fParentGroup; }
static pfConsoleCmdGroup *GetBaseGroup( void );
pfConsoleCmd *FindCommand( char *name );
pfConsoleCmd *FindCommandNoCase( char *name, UInt8 flags = 0, pfConsoleCmd *start = nil );
pfConsoleCmd *FindNestedPartialCommand( char *name, UInt32 *counter );
pfConsoleCmdGroup *FindSubGroup( char *name );
pfConsoleCmdGroup *FindSubGroupNoCase( char *name, UInt8 flags = 0, pfConsoleCmdGroup *start = nil );
pfConsoleCmd *GetFirstCommand( void ) { return fCommands; }
pfConsoleCmdGroup *GetFirstSubGroup( void ) { return fSubGroups; }
int IterateCommands(pfConsoleCmdIterator*, int depth=0);
static pfConsoleCmdGroup *FindSubGroupRecurse( const char *name );
static void DecBaseCmdGroupRef( void );
static void Dummy( void );
static void DummyJunior( void );
static void DummyNet( void );
static void DummyAvatar( void );
static void DummyCCR( void );
};
//// pfConsoleCmdParam Class Definition //////////////////////////////////////
class pfConsoleCmdParam
{
protected:
UInt8 fType;
typedef char *CharPtr;
union
{
int i;
float f;
bool b;
CharPtr s;
char c;
} fValue;
const int &IToInt( void ) const;
const float &IToFloat( void ) const;
const bool &IToBool( void ) const;
const CharPtr &IToString( void ) const;
const char &IToChar( void ) const;
public:
enum Types
{
kInt = 0,
kFloat,
kBool,
kString,
kChar,
kAny,
kNone = 0xff
};
operator int() const { return IToInt(); }
operator float() const { return IToFloat(); }
operator bool() const { return IToBool(); }
operator const CharPtr() const { return IToString(); }
operator char() const { return IToChar(); }
UInt8 GetType( void ) { return fType; }
void SetInt( int i ) { fValue.i = i; fType = kInt; }
void SetFloat( float f ) { fValue.f = f; fType = kFloat; }
void SetBool( bool b ) { fValue.b = b; fType = kBool; }
void SetString( CharPtr s ) { fValue.s = s; fType = kString; }
void SetChar( char c ) { fValue.c = c; fType = kChar; }
void SetAny( CharPtr s ) { fValue.s = s; fType = kAny; }
void SetNone( void ) { fType = kNone; }
};
//// pfConsoleCmd Class Definition ///////////////////////////////////////////
typedef void (*pfConsoleCmdPtr)( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) );
class pfConsoleCmd
{
protected:
char fName[ 128 ];
char *fHelpString;
pfConsoleCmdPtr fFunction;
hsBool fLocalOnly;
pfConsoleCmd *fNext;
pfConsoleCmd **fPrevPtr;
pfConsoleCmdGroup *fParentGroup;
hsExpander<UInt8> fSignature;
hsExpander<char *> fSigLabels;
void ICreateSignature( char *paramList );
public:
enum ParamTypes
{
kInt = 0,
kFloat,
kBool,
kString,
kChar,
kAny,
kEtc,
kNumTypes,
kNone = 0xff
};
static char fSigTypes[ kNumTypes ][ 8 ];
pfConsoleCmd( char *group, char *name, char *paramList, char *help, pfConsoleCmdPtr func, hsBool localOnly = false );
~pfConsoleCmd();
void Register( char *group, char *name );
void Unregister();
void Execute( Int32 numParams, pfConsoleCmdParam *params, void (*PrintFn)( const char * ) = nil );
void Link( pfConsoleCmd **prevPtr );
void Unlink( void );
pfConsoleCmd *GetNext( void ) { return fNext; }
char *GetName( void ) { return fName; }
char *GetHelp( void ) { return fHelpString; }
const char *GetSignature( void );
pfConsoleCmdGroup *GetParent( void ) { return fParentGroup; }
UInt8 GetSigEntry( UInt8 i );
};
class pfConsoleCmdIterator
{
public:
virtual void ProcessCmd(pfConsoleCmd*, int ) {}
virtual bool ProcessGroup(pfConsoleCmdGroup *, int) {return true;}
};
//// pfConsoleCmd Creation Macro /////////////////////////////////////////////
//
// This expands into 3 things:
// - A prototype for the function.
// - A declaration of a pfConsoleCmd object, which takes in that function
// as a parameter
// - The start of the function itself, so that the {} after the macro
// define the body of that function.
//
// PF_LOCAL_CONSOLE_CMD is identical, only it passes true for the localOnly flag.
// This isn't used currently and is here only for legacy.
// PF_CONSOLE_BASE_CMD doesn't belong to a group; it creates a global console function.
#define PF_CONSOLE_BASE_CMD( name, p, help ) \
void pfConsoleCmd_##name##_proc( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) ); \
pfConsoleCmd conCmd_##name( nil, #name, p, help, pfConsoleCmd_##name##_proc ); \
void pfConsoleCmd_##name##_proc( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) )
#define PF_CONSOLE_CMD( grp, name, p, help ) \
void pfConsoleCmd_##grp##_##name##_proc( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) ); \
pfConsoleCmd conCmd_##grp##_##name( #grp, #name, p, help, pfConsoleCmd_##grp##_##name##_proc ); \
void pfConsoleCmd_##grp##_##name##_proc( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) )
#define PF_LOCAL_CONSOLE_CMD( grp, name, p, help ) \
void pfConsoleCmd_##grp##_##name##_proc( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) ); \
pfConsoleCmd conCmd_##grp##_##name( #grp, #name, p, help, pfConsoleCmd_##grp##_##name##_proc, true ); \
void pfConsoleCmd_##grp##_##name##_proc( Int32 numParams, pfConsoleCmdParam *params, void (*PrintString)( const char * ) )
//// pfConsoleCmdGroup Creation Macro ////////////////////////////////////////
#define PF_CONSOLE_GROUP( name ) \
pfConsoleCmdGroup conGroup_##name( #name, nil );
#define PF_CONSOLE_SUBGROUP( parent, name ) \
pfConsoleCmdGroup conGroup_##parent##_##name( #name, #parent );
#endif //_pfConsoleCmd_h

View File

@ -0,0 +1,276 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleContext //
// //
//////////////////////////////////////////////////////////////////////////////
#include "hsTypes.h"
#include "pfConsoleContext.h"
//// Static Root Context /////////////////////////////////////////////////////
pfConsoleContext pfConsoleContext::fRootContext( "global" );
pfConsoleContext &pfConsoleContext::GetRootContext( void )
{
return fRootContext;
}
//// Constructor/Destructor //////////////////////////////////////////////////
pfConsoleContext::pfConsoleContext( const char *name )
{
fName = ( name != nil ) ? hsStrcpy( name ) : nil;
fAddWhenNotFound = true;
}
pfConsoleContext::~pfConsoleContext()
{
Clear();
delete [] fName;
}
//// Clear ///////////////////////////////////////////////////////////////////
void pfConsoleContext::Clear( void )
{
Int32 idx;
for( idx = fVarValues.GetCount() - 1; idx >= 0; idx-- )
RemoveVar( idx );
}
//// Getters /////////////////////////////////////////////////////////////////
UInt32 pfConsoleContext::GetNumVars( void ) const
{
hsAssert( fVarValues.GetCount() == fVarNames.GetCount(), "Mismatch in console var context arrays" );
return fVarValues.GetCount();
}
const char *pfConsoleContext::GetVarName( UInt32 idx ) const
{
hsAssert( fVarValues.GetCount() == fVarNames.GetCount(), "Mismatch in console var context arrays" );
if( idx >= fVarNames.GetCount() )
{
hsAssert( false, "GetVarName() index out of range for console context" );
return nil;
}
return fVarNames[ idx ];
}
pfConsoleCmdParam &pfConsoleContext::GetVarValue( UInt32 idx ) const
{
hsAssert( fVarValues.GetCount() == fVarNames.GetCount(), "Mismatch in console var context arrays" );
hsAssert( idx < fVarValues.GetCount(), "GetVarValue() index out of range for console context" );
return fVarValues[ idx ];
}
//// FindVar /////////////////////////////////////////////////////////////////
Int32 pfConsoleContext::FindVar( const char *name ) const
{
UInt32 idx;
hsAssert( fVarValues.GetCount() == fVarNames.GetCount(), "Mismatch in console var context arrays" );
for( idx = 0; idx < fVarNames.GetCount(); idx++ )
{
if( stricmp( name, fVarNames[ idx ] ) == 0 )
{
return (Int32)idx;
}
}
return -1;
}
//// RemoveVar ///////////////////////////////////////////////////////////////
void pfConsoleContext::RemoveVar( UInt32 idx )
{
hsAssert( fVarValues.GetCount() == fVarNames.GetCount(), "Mismatch in console var context arrays" );
if( idx >= fVarValues.GetCount() )
{
hsAssert( false, "RemoveVar() index out of range for console context" );
return;
}
delete [] fVarNames[ idx ];
if( fVarValues[ idx ].GetType() == pfConsoleCmdParam::kString )
// Necessary because the params won't delete the data themselves
delete [] ( (char *)fVarValues[ idx ] );
fVarNames.Remove( idx );
fVarValues.Remove( idx );
}
//// AddVar Variants /////////////////////////////////////////////////////////
void pfConsoleContext::IAddVar( const char *name, const pfConsoleCmdParam &value )
{
fVarNames.Append( hsStrcpy( name ) );
fVarValues.Append( value );
// Remember, params won't know any better, since by default they don't own a copy of their string
UInt32 idx = fVarValues.GetCount() - 1;
if( fVarValues[ idx ].GetType() == pfConsoleCmdParam::kString )
fVarValues[ idx ].SetString( hsStrcpy( fVarValues[ idx ] ) );
}
void pfConsoleContext::AddVar( const char *name, const pfConsoleCmdParam &value )
{
Int32 idx = FindVar( name );
if( idx != -1 )
{
hsAssert( false, "AddVar() failed because variable already in console context" );
return;
}
IAddVar( name, value );
}
void pfConsoleContext::AddVar( const char *name, int value )
{
pfConsoleCmdParam param;
param.SetInt( value );
AddVar( name, param );
}
void pfConsoleContext::AddVar( const char *name, float value )
{
pfConsoleCmdParam param;
param.SetFloat( value );
AddVar( name, param );
}
void pfConsoleContext::AddVar( const char *name, const char *value )
{
pfConsoleCmdParam param;
param.SetString( (char *)value ); // It's ok, we'll be copying it soon 'nuf
AddVar( name, param );
}
void pfConsoleContext::AddVar( const char *name, char value )
{
pfConsoleCmdParam param;
param.SetChar( value );
AddVar( name, param );
}
void pfConsoleContext::AddVar( const char *name, bool value )
{
pfConsoleCmdParam param;
param.SetBool( value );
AddVar( name, param );
}
//// SetVar Variants /////////////////////////////////////////////////////////
hsBool pfConsoleContext::SetVar( UInt32 idx, const pfConsoleCmdParam &value )
{
hsAssert( fVarValues.GetCount() == fVarNames.GetCount(), "Mismatch in console var context arrays" );
if( idx >= fVarValues.GetCount() )
{
hsAssert( false, "SetVar() index out of range for console context" );
return false;
}
if( fVarValues[ idx ].GetType() == pfConsoleCmdParam::kString )
{
// Remember, params won't know any better, since by default they don't own a copy of their string
delete [] ( (char *)fVarValues[ idx ] );
}
fVarValues[ idx ] = value;
if( fVarValues[ idx ].GetType() == pfConsoleCmdParam::kString )
fVarValues[ idx ].SetString( hsStrcpy( fVarValues[ idx ] ) );
return true;
}
hsBool pfConsoleContext::SetVar( const char *name, const pfConsoleCmdParam &value )
{
Int32 idx = FindVar( name );
if( idx == -1 )
{
if( fAddWhenNotFound )
{
// Don't panic, just add
IAddVar( name, value );
return true;
}
return false;
}
return SetVar( idx, value );
}
hsBool pfConsoleContext::SetVar( const char *name, int value )
{
pfConsoleCmdParam param;
param.SetInt( value );
return SetVar( name, param );
}
hsBool pfConsoleContext::SetVar( const char *name, float value )
{
pfConsoleCmdParam param;
param.SetFloat( value );
return SetVar( name, param );
}
hsBool pfConsoleContext::SetVar( const char *name, const char *value )
{
pfConsoleCmdParam param;
param.SetString( (char *)value ); // Don't worry, we'll be copying it soon 'nuf
return SetVar( name, param );
}
hsBool pfConsoleContext::SetVar( const char *name, char value )
{
pfConsoleCmdParam param;
param.SetChar( value );
return SetVar( name, param );
}
hsBool pfConsoleContext::SetVar( const char *name, bool value )
{
pfConsoleCmdParam param;
param.SetBool( value );
return SetVar( name, param );
}

View File

@ -0,0 +1,95 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleContext Header //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _pfConsoleContext_h
#define _pfConsoleContext_h
#include "hsTypes.h"
#include "pfConsoleCmd.h"
//// Class Definition ////////////////////////////////////////////////////////
class pfConsoleContext
{
protected:
hsBool fAddWhenNotFound; // Controls whether we add variables on Set() calls if they're not found
char *fName;
hsTArray<char *> fVarNames;
hsTArray<pfConsoleCmdParam> fVarValues;
void IAddVar( const char *name, const pfConsoleCmdParam &value );
static pfConsoleContext fRootContext;
public:
pfConsoleContext( const char *name );
virtual ~pfConsoleContext();
void Clear( void );
UInt32 GetNumVars( void ) const;
const char *GetVarName( UInt32 idx ) const;
pfConsoleCmdParam &GetVarValue( UInt32 idx ) const;
Int32 FindVar( const char *name ) const;
void RemoveVar( UInt32 idx );
void AddVar( const char *name, const pfConsoleCmdParam &value );
void AddVar( const char *name, int value );
void AddVar( const char *name, float value );
void AddVar( const char *name, const char *value );
void AddVar( const char *name, char value );
void AddVar( const char *name, bool value );
hsBool SetVar( UInt32 idx, const pfConsoleCmdParam &value );
hsBool SetVar( const char *name, const pfConsoleCmdParam &value );
hsBool SetVar( const char *name, int value );
hsBool SetVar( const char *name, float value );
hsBool SetVar( const char *name, const char *value );
hsBool SetVar( const char *name, char value );
hsBool SetVar( const char *name, bool value );
// Decide whether Sets() on nonexistant variables will fail or add a new variable
void SetAddWhenNotFound( hsBool f ) { fAddWhenNotFound = f; }
hsBool GetAddWhenNotFound( void ) const { return fAddWhenNotFound; }
static pfConsoleContext &GetRootContext( void );
};
#endif //_pfConsoleContext_h

View File

@ -0,0 +1,36 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef pfConsoleCreatable_inc
#define pfConsoleCreatable_inc
#include "../pnFactory/plCreator.h"
#include "pfConsole.h"
REGISTER_CREATABLE( pfConsole );
#endif // pfConsoleCreatable_inc

View File

@ -0,0 +1,149 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleDirSrc Functions //
// //
//////////////////////////////////////////////////////////////////////////////
#include "pfConsoleDirSrc.h"
#include "hsExceptions.h"
#ifdef HS_BUILD_FOR_WIN32
#define WIN32_EXTRA_LEAN
#define WIN32_LEAN_AND_MEAN
#ifndef _WINDOWS_H_ // redundant include guard to minimize compile times
#define _WINDOWS_H_
#include <windows.h>
#endif // _WINDOWS_H_
#include <winbase.h>
#include <sstream>
//// ParseDirectory //////////////////////////////////////////////////////////
hsBool pfConsoleDirSrc::ParseDirectory(const std::string& path, const std::string& mask /* = "*.*" */)
{
wchar* wPath = hsStringToWString(path.c_str());
wchar* wMask = hsStringToWString(mask.c_str());
hsBool ret = ParseDirectory(wPath, wMask);
delete [] wPath;
delete [] wMask;
return ret;
}
hsBool pfConsoleDirSrc::ParseDirectory(const std::wstring& path, const std::wstring& mask /* = L"*.*" */)
{
std::wstringstream search;
std::wstring file;
WIN32_FIND_DATAW findInfo;
HANDLE handle;
hsAssert( fEngine != nil, "Cannot do a dir execute without an engine!" );
search << path << L"\\" << mask;
handle = FindFirstFileW(search.str().c_str(), &findInfo);
if (handle == INVALID_HANDLE_VALUE)
return false;
do
{
if (!( findInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
std::wstringstream fileAndPath;
fileAndPath << path << L"\\" << findInfo.cFileName;
if (AlreadyProcessedFile(path, findInfo.cFileName))
continue;
AddProcessedFile(path, findInfo.cFileName);
if (!fEngine->ExecuteFile(fileAndPath.str().c_str()))
{
// Change the following line once we have a better way of reporting
// errors in the parsing
std::wstringstream error;
std::wstringstream caption;
wchar* errorMsg = hsStringToWString(fEngine->GetErrorMsg());
wchar* errorLine = hsStringToWString(fEngine->GetLastErrorLine());
caption << L"Error parsing " << findInfo.cFileName;
error << errorMsg << L":\n\nCommand: '" << errorLine << L"'\n\nPress OK to continue parsing files.";
hsMessageBox(error.str().c_str(), caption.str().c_str(), hsMessageBoxNormal);
delete [] errorMsg;
delete [] errorLine;
FindClose(handle);
SetCheckProcessedFiles(true);
return false;
}
}
} while (FindNextFileW(handle, &findInfo) != 0);
FindClose(handle);
SetCheckProcessedFiles(true);
return true;
}
#else
#error This needs to be implemented for this platform!!!!
#endif
void pfConsoleDirSrc::ResetProcessedFiles()
{
int i;
for(i=0;i<fProcessedFiles.size(); i++)
delete fProcessedFiles[i];
fProcessedFiles.clear();
}
//
// note: this n^2 linear search should be replaced with something
// faster if we have lots of init files and turn on the checkProcessing option.
//
hsBool pfConsoleDirSrc::AlreadyProcessedFile(const std::wstring& path, const std::wstring& file)
{
if (fCheckProcessedFiles)
{
int i;
for(i=0; i<fProcessedFiles.size(); i++)
{
if (file == fProcessedFiles[i]->fFile && path == fProcessedFiles[i]->fPath)
return true;
}
}
return false;
}
void pfConsoleDirSrc::AddProcessedFile(const std::wstring& path, const std::wstring& file)
{
fProcessedFiles.push_back(TRACKED_NEW FileName(path, file));
}

View File

@ -0,0 +1,89 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleDirSrc Header //
// //
//// Description /////////////////////////////////////////////////////////////
// //
// Simple wrapper for parsing an entire directory of files and executing //
// each one through the pfConsoleEngine object given. //
// I.E. the source for the console commmands is a directory of files, //
// hence it's a Console Directory Source, or ConsoleDirSrc. :) //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _pfConsoleDirSrc_h
#define _pfConsoleDirSrc_h
#include "hsTypes.h"
#include "hsStlUtils.h"
#include "pfConsoleEngine.h"
//// pfConsoleDirSrc Class Definition ////////////////////////////////////////
class pfConsoleDirSrc
{
protected:
pfConsoleEngine *fEngine;
struct FileName
{
std::wstring fPath;
std::wstring fFile;
FileName() : fPath(L""), fFile(L"") {}
FileName(const std::wstring& p, const std::wstring& f) : fPath(p), fFile(f) {}
};
std::vector<FileName*> fProcessedFiles; // list of init files we've already executed
hsBool fCheckProcessedFiles; // set to check and skip files init files we've already executed
public:
pfConsoleDirSrc(pfConsoleEngine *engine) : fCheckProcessedFiles(false) { fEngine = engine; }
pfConsoleDirSrc(pfConsoleEngine *engine, const std::string& path, const std::string& mask = "*.ini") :
fCheckProcessedFiles(false)
{
fEngine = engine;
ParseDirectory(path, mask);
}
pfConsoleDirSrc(pfConsoleEngine *engine, const std::wstring& path, const std::wstring& mask = L"*.ini") :
fCheckProcessedFiles(false)
{
fEngine = engine;
ParseDirectory(path, mask);
}
~pfConsoleDirSrc() { ResetProcessedFiles(); }
// Steps through the given directory and executes all files with the console engine
hsBool ParseDirectory(const std::string& path, const std::string& mask = "*.*");
hsBool ParseDirectory(const std::wstring& path, const std::wstring& mask = L"*.*");
void ResetProcessedFiles();
hsBool AlreadyProcessedFile(const std::wstring& path, const std::wstring& file);
void AddProcessedFile(const std::wstring& path, const std::wstring& file);
void SetCheckProcessedFiles(hsBool c) { fCheckProcessedFiles=c; }
};
#endif //_pfConsoleDirSrc_h

View File

@ -0,0 +1,579 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleEngine Functions //
// //
//////////////////////////////////////////////////////////////////////////////
#include "pfConsoleEngine.h"
#include "pfConsoleCmd.h"
#include "pfConsoleContext.h"
#include "../plFile/plEncryptedStream.h"
const Int32 pfConsoleEngine::fMaxNumParams = 16;
const char pfConsoleEngine::fTokenSeparators[] = " =\r\n\t,";
const char pfConsoleEngine::fTokenGrpSeps[] = " =\r\n._\t,";
//// Constructor & Destructor ////////////////////////////////////////////////
pfConsoleEngine::pfConsoleEngine()
{
}
pfConsoleEngine::~pfConsoleEngine()
{
}
//// PrintCmdHelp ////////////////////////////////////////////////////////////
hsBool pfConsoleEngine::PrintCmdHelp( char *name, void (*PrintFn)( const char * ) )
{
pfConsoleCmd *cmd;
pfConsoleCmdGroup *group, *subGrp;
char *ptr;
static char string[ 512 ];
static char tempString[ 512 ];
UInt32 i;
/// Scan for subgroups. This can be an empty loop
group = pfConsoleCmdGroup::GetBaseGroup();
ptr = strtok( name, fTokenGrpSeps );
while( ptr != nil )
{
// Take this token and check to see if it's a group
if( ( subGrp = group->FindSubGroupNoCase( ptr ) ) != nil )
group = subGrp;
else
break;
ptr = strtok( nil, fTokenGrpSeps );
}
if( ptr == nil )
{
if( group == nil )
{
ISetErrorMsg( "Invalid command syntax" );
return false;
}
// Print help for this group
if( group == pfConsoleCmdGroup::GetBaseGroup() )
strcpy( string, "Base commands and groups:" );
else
sprintf( string, "Group %s:", group->GetName() );
PrintFn( string );
PrintFn( " Subgroups:" );
for( subGrp = group->GetFirstSubGroup(); subGrp != nil; subGrp = subGrp->GetNext() )
{
sprintf( string, " %s", subGrp->GetName() );
PrintFn( string );
}
PrintFn( " Commands:" );
for( cmd = group->GetFirstCommand(); cmd != nil; cmd = cmd->GetNext() )
{
for( ptr = cmd->GetHelp(), i = 0; ptr[ i ] != 0 && ptr[ i ] != '\n'; i++ )
tempString[ i ] = ptr[ i ];
tempString[ i ] = 0;
sprintf( string, " %s: %s", cmd->GetName(), tempString );
PrintFn( string );
}
return true;
}
/// OK, so what we found wasn't a group. Which means we need a command...
cmd = group->FindCommandNoCase( ptr );
if( cmd == nil )
{
ISetErrorMsg( "Invalid syntax: command not found" );
return false;
}
/// That's it!
sprintf( string, "\nHelp for the command %s:", cmd->GetName() );
PrintFn( string );
sprintf( string, "\\i%s", cmd->GetHelp() );
PrintFn( string );
sprintf( string, "\\iUsage: %s", cmd->GetSignature() );
PrintFn( string );
return true;
}
//// GetCmdSignature /////////////////////////////////////////////////////////
const char *pfConsoleEngine::GetCmdSignature( char *name )
{
pfConsoleCmd *cmd;
pfConsoleCmdGroup *group, *subGrp;
char *ptr;
static char string[ 512 ];
/// Scan for subgroups. This can be an empty loop
group = pfConsoleCmdGroup::GetBaseGroup();
ptr = strtok( name, fTokenGrpSeps );
while( ptr != nil )
{
// Take this token and check to see if it's a group
if( ( subGrp = group->FindSubGroupNoCase( ptr ) ) != nil )
group = subGrp;
else
break;
ptr = strtok( nil, fTokenGrpSeps );
}
if( ptr == nil )
{
ISetErrorMsg( "Invalid command syntax" );
return nil;
}
/// OK, so what we found wasn't a group. Which means we need a command...
cmd = group->FindCommandNoCase( ptr );
if( cmd == nil )
{
ISetErrorMsg( "Invalid syntax: command not found" );
return nil;
}
/// That's it!
return (char *)cmd->GetSignature();
}
//// Dummy Local Function ////////////////////////////////////////////////////
void DummyPrintFn( const char *line )
{
}
//// ExecuteFile /////////////////////////////////////////////////////////////
hsBool pfConsoleEngine::ExecuteFile( const char *fileName )
{
wchar* wFilename = hsStringToWString(fileName);
hsBool ret = ExecuteFile(wFilename);
delete [] wFilename;
return ret;
}
hsBool pfConsoleEngine::ExecuteFile( const wchar *fileName )
{
char string[ 512 ];
int line;
hsStream* stream = plEncryptedStream::OpenEncryptedFile(fileName);
if( !stream )
{
ISetErrorMsg( "Cannot open given file" );
// return false;
/// THIS IS BAD: because of the asserts we throw after this if we return false, a missing
/// file will throw an assert. This is all well and good except for the age-specific .fni files,
/// which aren't required to be there and rely on this functionality to test whether the file is
/// present. Once age-specific .fni's are gone, reinstate the return false here. -mcn
return true;
}
for( line = 1; stream->ReadLn( string, sizeof( string ) ); line++ )
{
strncpy( fLastErrorLine, string, sizeof( fLastErrorLine ) );
if( !RunCommand( string, DummyPrintFn ) )
{
sprintf( string, "Error in console file %s, command line %d: %s", fileName, line, fErrorMsg );
ISetErrorMsg( string );
stream->Close();
delete stream;
return false;
}
}
stream->Close();
delete stream;
fLastErrorLine[ 0 ] = 0;
return true;
}
//// RunCommand //////////////////////////////////////////////////////////////
// Updated 2.14.2001 mcn to support spaces, _ or . as group separators. This
// requires tokenizing the entire line and searching the tokens one by one,
// parsing them first as groups, then commands and then params.
hsBool pfConsoleEngine::RunCommand( char *line, void (*PrintFn)( const char * ) )
{
pfConsoleCmd *cmd;
pfConsoleCmdGroup *group, *subGrp;
Int32 numParams, i, numQuotedParams = 0;
pfConsoleCmdParam paramArray[ fMaxNumParams + 1 ];
char *ptr;
hsBool valid = true;
hsAssert( line != nil, "Bad parameter to RunCommand()" );
/// Loop #1: Scan for subgroups. This can be an empty loop
group = pfConsoleCmdGroup::GetBaseGroup();
ptr = strtok( line, fTokenGrpSeps );
while( ptr != nil )
{
// Take this token and check to see if it's a group
if( ( subGrp = group->FindSubGroupNoCase( ptr ) ) != nil )
group = subGrp;
else
break;
ptr = strtok( nil, fTokenGrpSeps );
}
if( ptr == nil )
{
ISetErrorMsg( "Invalid command syntax" );
return false;
}
/// OK, so what we found wasn't a group. Which means we need a command next
cmd = group->FindCommandNoCase( ptr );
if( cmd == nil )
{
ISetErrorMsg( "Invalid syntax: command not found" );
return false;
}
/// We have the group, we have the command from that group. So continue
/// tokenizing (with the new separators now, mind you) and turn them into
/// params
for( numParams = numQuotedParams = 0; numParams < fMaxNumParams
&& ( ptr = strtok( nil, fTokenSeparators ) ) != nil
&& valid; numParams++ )
{
if( ptr[ 0 ] == '\'' || ptr[ 0 ] == '"' )
{
// String parameter--keep getting tokens until we hit the other end
// Note: since params take pointers to strings, we have to have unique temp strings
// for each quoted param we parse. So we have a static array here to a) do so, b)
// avoid having to delete them afterwards, and thus c) reduce overhead.
static char tempStrings[ fMaxNumParams ][ 512 ];
char *tempStr = tempStrings[ numQuotedParams++ ], toSearch[ 2 ] = "'";
toSearch[ 0 ] = ptr[ 0 ];
if( strlen( ptr ) >= sizeof( tempStrings[ 0 ] ) ) // They're all the same, after all...
{
ISetErrorMsg( "Invalid syntax: quoted parameter too long" );
return false;
}
if( strlen( ptr ) > 1 && ptr[ strlen( ptr ) - 1 ] == toSearch[ 0 ] )
{
// Single word string
strcpy( tempStr, ptr + 1 );
tempStr[ strlen( tempStr ) - 1 ] = 0;
}
else
{
// Multiple word string
sprintf( tempStr, "%s ", ptr + 1 ); // Not perfect, but close
ptr = strtok( nil, toSearch );
if( ptr == nil )
{
ISetErrorMsg( "Invalid syntax: unterminated quoted parameter" );
return false;
}
if( strlen( ptr ) + strlen( tempStr ) >= sizeof( tempStrings[ 0 ] ) ) // They're all the same, after all...
{
ISetErrorMsg( "Invalid syntax: quoted parameter too long" );
return false;
}
strcat( tempStr, ptr );
}
valid = IConvertToParam( cmd->GetSigEntry( (UInt8)numParams ), tempStr, &paramArray[ numParams ] );
}
else
{
// Normal parameter
// Special case for context variables--if we're specifying one, we want to just grab
// the value of it and return that instead
valid = false;
if( ptr[ 0 ] == '$' )
{
pfConsoleContext &context = pfConsoleContext::GetRootContext();
// Potential variable, see if we can find it
Int32 idx = context.FindVar( ptr + 1 );
if( idx == -1 )
{
ISetErrorMsg( "Invalid console variable name" );
}
else
{
// Just copy. Note that this will copy string pointers, but so long as the variable in
// question doesn't change, we'll be OK...
paramArray[ numParams ] = context.GetVarValue( idx );
valid = true;
}
}
if( !valid )
valid = IConvertToParam( cmd->GetSigEntry( (UInt8)numParams ), ptr, &paramArray[ numParams ] );
}
}
for( i = numParams; i < fMaxNumParams + 1; i++ )
paramArray[ i ].SetNone();
if( !valid || ( cmd->GetSigEntry( (UInt8)numParams ) != pfConsoleCmd::kAny &&
cmd->GetSigEntry( (UInt8)numParams ) != pfConsoleCmd::kNone ) )
{
// Print help string and return
static char string[ 512 ];
ISetErrorMsg( "" ); // Printed on next line
PrintFn( "Invalid parameters to command" );
sprintf( string, "Usage: %s", cmd->GetSignature() );
PrintFn( string );
return false;
}
/// Execute it and return
cmd->Execute( numParams, paramArray, PrintFn );
return true;
}
//// IConvertToParam /////////////////////////////////////////////////////////
// Converts a null-terminated string representing a parameter to a
// pfConsoleCmdParam argument.
hsBool pfConsoleEngine::IConvertToParam( UInt8 type, char *string, pfConsoleCmdParam *param )
{
char *c, expChars[] = "dDeE+-.";
hsBool hasDecimal = false, hasLetters = false;
if( type == pfConsoleCmd::kNone )
return false;
for( c = string; *c != 0; c++ )
{
if( !isdigit( *c ) )
{
if( c == string && ( *c == '-' || *c == '+' ) )
{
// Do nothing--perfectly legal to have these at the beginning of an int
}
else if( strchr( expChars, *c ) != nil )
hasDecimal = true;
else
hasLetters = true;
}
}
if( type == pfConsoleCmd::kAny )
{
/// Want "any"
param->SetAny( string );
}
else if( type == pfConsoleCmd::kString )
{
/// Want just a string
param->SetString( string );
}
else if( type == pfConsoleCmd::kFloat )
{
if( hasLetters )
return false;
param->SetFloat( (float)atof( string ) );
}
else if( type == pfConsoleCmd::kInt )
{
if( hasLetters || hasDecimal )
return false;
param->SetInt( atoi( string ) );
}
else if( type == pfConsoleCmd::kBool )
{
if( stricmp( string, "true" ) == 0 || stricmp( string, "t" ) == 0 )
param->SetBool( true );
else if( stricmp( string, "false" ) == 0 || stricmp( string, "f" ) == 0 )
param->SetBool( false );
else if( atoi( string ) == 0 )
param->SetBool( false );
else
param->SetBool( true );
}
return true;
}
//// FindPartialCmd //////////////////////////////////////////////////////////
// Given a string which is the beginning of a console command, modifies the
// string to represent the best match of command (or group) for that string.
// WARNING: modifies the string passed to it.
hsBool pfConsoleEngine::FindPartialCmd( char *line, hsBool findAgain, hsBool preserveParams )
{
pfConsoleCmd *cmd = nil;
pfConsoleCmdGroup *group, *subGrp;
hsBool foundMore = false;
static char *ptr = nil, *insertLoc = nil;
static pfConsoleCmd *lastCmd = nil;
static pfConsoleCmdGroup *lastGroup = nil, *lastParentGroup = nil;
static char newStr[ 256 ];
/// Repeat search
if( !findAgain )
{
lastCmd = nil;
lastGroup = nil;
}
/// New search
if( strlen( line ) > sizeof( newStr ) )
return false;
newStr[ 0 ] = 0;
insertLoc = newStr;
/// Loop #1: Scan for subgroups. This can be an empty loop
lastParentGroup = group = pfConsoleCmdGroup::GetBaseGroup();
ptr = strtok( line, fTokenGrpSeps );
while( ptr != nil )
{
// Take this token and check to see if it's a group
if( ( subGrp = group->FindSubGroupNoCase( ptr, 0/*pfConsoleCmdGroup::kFindPartial*/
, /*lastGroup*/nil ) ) != nil )
{
lastParentGroup = group;
group = subGrp;
strcat( newStr, group->GetName() );
insertLoc += strlen( group->GetName() );
}
else
break;
ptr = strtok( nil, fTokenGrpSeps );
strcat( newStr, "." );
insertLoc++;
}
if( ptr != nil )
{
// Still got at least one token left. Try to match to either
// a partial group or a partial command
if( ( subGrp = group->FindSubGroupNoCase( ptr, pfConsoleCmdGroup::kFindPartial, lastGroup ) ) != nil )
{
lastParentGroup = group;
lastGroup = group = subGrp;
strcat( newStr, group->GetName() );
strcat( newStr, "." );
}
else
{
cmd = group->FindCommandNoCase( ptr, pfConsoleCmdGroup::kFindPartial, lastCmd );
if( cmd == nil )
return false;
strcat( newStr, cmd->GetName() );
strcat( newStr, " " );
lastCmd = cmd;
}
}
if( preserveParams )
{
/// Preserve the rest of the string after the matched command
ptr = strtok( nil, "\0" );
if( ptr != nil )
strcat( newStr, ptr );
}
// Copy back!
strcpy( line, newStr );
return true;
}
//// FindNestedPartialCmd ////////////////////////////////////////////////////
// Same as FindPartialCmd, only starts from the global group and searches
// everything. The string passed should only be a partial command sans
// groups. numToSkip specifies how many matches to skip before returning one
// (so if numToSkip = 1, then this will return the second match found).
hsBool pfConsoleEngine::FindNestedPartialCmd( char *line, UInt32 numToSkip, hsBool preserveParams )
{
pfConsoleCmd *cmd;
/// Somewhat easier than FindPartialCmd...
cmd = pfConsoleCmdGroup::GetBaseGroup()->FindNestedPartialCommand( line, &numToSkip );
if( cmd == nil )
return false;
/// Recurse back up and get the group hierarchy
line[ 0 ] = 0;
IBuildCmdNameRecurse( cmd->GetParent(), line );
strcat( line, cmd->GetName() );
strcat( line, " " );
if( preserveParams )
{
/// Preserve the rest of the string after the matched command
}
return true;
}
//// IBuildCmdNameRecurse ////////////////////////////////////////////////////
void pfConsoleEngine::IBuildCmdNameRecurse( pfConsoleCmdGroup *group, char *string )
{
if( group == nil || group == pfConsoleCmdGroup::GetBaseGroup() )
return;
IBuildCmdNameRecurse( group->GetParent(), string );
strcat( string, group->GetName() );
strcat( string, "." );
}

View File

@ -0,0 +1,100 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfConsoleEngine Header //
// //
//// Description /////////////////////////////////////////////////////////////
// //
// The engine is where parsing and execution of console commands takes //
// place. It takes place independently of the interface, so that the //
// execution can happen from an INI file, from a screen-based console or //
// even a GUI interface. //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef _pfConsoleEngine_h
#define _pfConsoleEngine_h
#include "hsTypes.h"
#include "hsUtils.h"
//// pfConsoleEngine Class Definition ////////////////////////////////////////
class pfConsoleCmdParam;
class pfConsoleCmdGroup;
class pfConsoleEngine
{
private:
static const Int32 fMaxNumParams;
static const char fTokenSeparators[];
static const char fTokenGrpSeps[];
hsBool IConvertToParam( UInt8 type, char *string, pfConsoleCmdParam *param );
char fErrorMsg[ 128 ];
char fLastErrorLine[ 512 ];
void ISetErrorMsg( char *msg ) { hsStrncpy( fErrorMsg, msg, sizeof( fErrorMsg ) ); }
// Recursive function to build a string of the groups a command is in
void IBuildCmdNameRecurse( pfConsoleCmdGroup *group, char *string );
public:
pfConsoleEngine();
~pfConsoleEngine();
// Gets the signature for the command given (NO groups!)
const char *GetCmdSignature( char *name );
// Prints out the help for a given command (or group)
hsBool PrintCmdHelp( char *name, void (*PrintFn)( const char * ) );
// Breaks the given line into a command and parameters and runs the command
hsBool RunCommand( char *line, void (*PrintFn)( const char * ) );
// Executes the given file as a sequence of console commands
hsBool ExecuteFile( const char *fileName );
hsBool ExecuteFile( const wchar *fileName );
// Get the last reported error
const char *GetErrorMsg( void ) { return fErrorMsg; }
// Get the line for which the last reported error was for
const char *GetLastErrorLine( void ) { return fLastErrorLine; }
// Does command completion on a partially-complete console line
hsBool FindPartialCmd( char *line, hsBool findAgain = false, hsBool perserveParams = false );
// Does command completion without restrictions to any group, skipping the number of matches given
hsBool FindNestedPartialCmd( char *line, UInt32 numToSkip, hsBool perserveParams = false );
};
#endif //_pfConsoleEngine_h

View File

@ -0,0 +1,313 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTimer.h"
#include "pfDispatchLog.h"
#include "../plStatusLog/plStatusLog.h"
#include "../pnMessage/plMessage.h"
#include "../pnKeyedObject/plKey.h"
#include "hsWindows.h"
bool DumpSpecificMsgInfo(plMessage* msg, std::string& info);
plDispatchLog::plDispatchLog() :
fLog(nil),
fStartTicks(hsTimer::GetFullTickCount())
{
fLog = plStatusLogMgr::GetInstance().CreateStatusLog(20, "Dispatch.log", plStatusLog::kAlignToTop | plStatusLog::kFilledBackground | plStatusLog::kRawTimeStamp);
fIncludeTypes.SetSize(plFactory::GetNumClasses());
}
plDispatchLog::~plDispatchLog()
{
delete fLog;
}
void plDispatchLog::InitInstance()
{
static plDispatchLog dispatchLog;
fInstance = &dispatchLog;
}
void plDispatchLog::LogStatusBarChange(const char* name, const char* action)
{
fLog->AddLineF("----- Status bar '%s' %s -----", name, action);
#ifdef HS_BUILD_FOR_WIN32
MEMORYSTATUS ms;
GlobalMemoryStatus(&ms);
MEMORY_BASIC_INFORMATION mbi;
memset(&mbi, 0, sizeof(MEMORY_BASIC_INFORMATION));
// Note: this will return shared mem too on Win9x. There's a way to catch that, but it's too slow -Colin
UInt32 processMemUsed = 0;
void* curAddress = 0;
while (VirtualQuery(curAddress, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == sizeof(MEMORY_BASIC_INFORMATION))
{
if (mbi.State == MEM_COMMIT && mbi.Type == MEM_PRIVATE)
processMemUsed += mbi.RegionSize;
curAddress = ((BYTE*)mbi.BaseAddress) + mbi.RegionSize;
}
#define ToMB(mem) float(mem) / (1024.f*1024.f)
fLog->AddLineF("# Mem stats");
fLog->AddLineF("# Physical: %.1f MB used %.1f MB free", ToMB(ms.dwTotalPhys-ms.dwAvailPhys), ToMB(ms.dwAvailPhys));
fLog->AddLineF("# Virtual: %.1f MB used %.1f MB free", ToMB(ms.dwTotalVirtual-ms.dwAvailVirtual), ToMB(ms.dwAvailVirtual));
fLog->AddLineF("# Pagefile: %.1f MB used %.1f MB free", ToMB(ms.dwTotalPageFile-ms.dwAvailPageFile), ToMB(ms.dwAvailPageFile));
fLog->AddLineF("# Process: %.1f MB used", ToMB(processMemUsed));
#endif // HS_BUILD_FOR_WIN32
}
void plDispatchLog::LogLongReceive(const char* keyname, const char* className, UInt32 clonePlayerID, plMessage* msg, float ms)
{
std::string info;
if (DumpSpecificMsgInfo(msg, info))
fLog->AddLineF("%-30s[%7u](%-20s) took %6.1f ms to receive %s[%s]\n", keyname, clonePlayerID, className, ms, msg->ClassName(), info.c_str());
else
fLog->AddLineF("%-30s[%7u](%-20s) took %6.1f ms to receive %s\n", keyname, clonePlayerID, className, ms, msg->ClassName());
}
void plDispatchLog::DumpMsg(plMessage* msg, int numReceivers, int sendTimeMs, Int32 indent)
{
if (!msg)
return;
hsBool found=fIncludeTypes.IsBitSet(msg->ClassIndex());
if (found && !hsCheckBits(fFlags, plDispatchLogBase::kInclude))
// it's an exclude list and we found it
return;
if (!found && hsCheckBits(fFlags, plDispatchLogBase::kInclude))
// it's an include list and we didn't find it
return;
static hsScalar lastTime=0;
hsScalar curTime = (hsScalar)hsTimer::GetSysSeconds();
if (lastTime!=curTime)
{
// add linebreak for new frame
fLog->AddLine("\n");
}
float sendTime = hsTimer::FullTicksToMs(hsTimer::GetFullTickCount() - fStartTicks);
char indentStr[50];
indent = hsMinimum(indent, sizeof(indentStr)-1);
memset(indentStr, ' ', indent);
indentStr[indent] = '\0';
fLog->AddLineF("%sDispatched (%d) %d ms: time=%d CName=%s, sndr=%s, rcvr(%d)=%s, flags=0x%lx, tstamp=%f\n",
indentStr, numReceivers, sendTimeMs,
int(sendTime), msg->ClassName(), msg->fSender?msg->fSender->GetName():"nil",
msg->GetNumReceivers(), msg->GetNumReceivers() && msg->GetReceiver(0)
? msg->GetReceiver(0)->GetName():"nil",
msg->fBCastFlags, msg->fTimeStamp);
lastTime=curTime;
}
void plDispatchLog::AddFilterType(UInt16 hClass)
{
if (hClass>=plFactory::GetNumClasses())
return;
int i;
for( i = 0; i < plFactory::GetNumClasses(); i++ )
{
if( plFactory::DerivesFrom(hClass, i) )
AddFilterExactType(i);
}
}
void plDispatchLog::AddFilterExactType(UInt16 type)
{
if (type<plFactory::GetNumClasses())
fIncludeTypes.SetBit(type);
}
void plDispatchLog::RemoveFilterType(UInt16 hClass)
{
if (hClass>=plFactory::GetNumClasses())
return;
int i;
for( i = 0; i < plFactory::GetNumClasses(); i++ )
{
if( plFactory::DerivesFrom(hClass, i) )
RemoveFilterExactType(i);
}
}
void plDispatchLog::RemoveFilterExactType(UInt16 type)
{
if (type<plFactory::GetNumClasses())
fIncludeTypes.ClearBit(type);
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#include "../pnMessage/plClientMsg.h"
#include "../pfMessage/pfKIMsg.h"
#include "../pnKeyedObject/hsKeyedObject.h"
#include "../plResMgr/plKeyFinder.h"
#include "../plResMgr/plPageInfo.h"
static bool DumpSpecificMsgInfo(plMessage* msg, std::string& info)
{
#ifndef PLASMA_EXTERNAL_RELEASE // Don't bloat up the external release with all these strings
pfKIMsg* kiMsg = pfKIMsg::ConvertNoRef(msg);
if (kiMsg)
{
const char* typeName = "(unknown)";
#define PrintKIType(type) if (kiMsg->GetCommand() == pfKIMsg::##type) typeName = #type;
PrintKIType(kHACKChatMsg); // send chat message via pfKIMsg
PrintKIType(kEnterChatMode); // toggle chat mode
PrintKIType(kSetChatFadeDelay); // set the chat delay
PrintKIType(kSetTextChatAdminMode); // set the chat admin mode... not used (see CCR)
PrintKIType(kDisableKIandBB); // disable KI and blackbar (for things like AvaCusta)
PrintKIType(kEnableKIandBB); // re-enable the KI and blackbar
PrintKIType(kYesNoDialog); // display a Yes/No dialog
PrintKIType(kAddPlayerDevice); // add a device player list); such as imager
PrintKIType(kRemovePlayerDevice); // remove a device from player list
PrintKIType(kUpgradeKILevel); // upgrade the KI to higher level
PrintKIType(kDowngradeKILevel); // downgrade KI to next lower level
PrintKIType(kRateIt); // display the "RateIt"(tm) dialog
PrintKIType(kSetPrivateChatChannel); // set the private chat channel (for private rooms)
PrintKIType(kUnsetPrivateChatChannel); // unset private chat channel
PrintKIType(kStartBookAlert); // blink the book image on the blackbar
PrintKIType(kMiniBigKIToggle); // shortcut to toggling the miniKI/bigKI
PrintKIType(kKIPutAway); // shortcut to hiding all of the KI
PrintKIType(kChatAreaPageUp); // shortcut to paging up the chat area
PrintKIType(kChatAreaPageDown); // shortcut to paging down the chat area
PrintKIType(kChatAreaGoToBegin); // shortcut to going to the beginning of the chat area
PrintKIType(kChatAreaGoToEnd); // shortcut to going to the end of the chat area
PrintKIType(kKITakePicture); // shortcut to taking a picture in the KI
PrintKIType(kKICreateJournalNote); // shortcut to creating a journal note in the KI
PrintKIType(kKIToggleFade); // shortcut to toggle fade mode
PrintKIType(kKIToggleFadeEnable); // shortcut to toggling fade enabled
PrintKIType(kKIChatStatusMsg); // display status message in chat window
PrintKIType(kKILocalChatStatusMsg); // display status message in chat window
PrintKIType(kKIUpSizeFont); // bump up the size of the chat area font
PrintKIType(kKIDownSizeFont); // down size the font of the chat area
PrintKIType(kKIOpenYeehsaBook); // open the playerbook if not already open
PrintKIType(kKIOpenKI); // open up in degrees the KI
PrintKIType(kKIShowCCRHelp); // show the CCR help dialog
PrintKIType(kKICreateMarker); // create a marker
PrintKIType(kKICreateMarkerFolder); // create a marker folder in the current Age's journal folder
PrintKIType(kKILocalChatErrorMsg); // display error message in chat window
PrintKIType(kKIPhasedAllOn); // turn on all the phased KI functionality
PrintKIType(kKIPhasedAllOff); // turn off all the phased KI functionality
PrintKIType(kKIOKDialog); // display an OK dialog box (localized)
PrintKIType(kDisableYeeshaBook); // don't allow linking with the Yeesha book (gameplay)
PrintKIType(kEnableYeeshaBook); // re-allow linking with the Yeesha book
PrintKIType(kQuitDialog); // put up quit dialog
PrintKIType(kTempDisableKIandBB); // temp disable KI and blackbar (done by av system)
PrintKIType(kTempEnableKIandBB); // temp re-enable the KI and blackbar (done by av system)
PrintKIType(kDisableEntireYeeshaBook); // disable the entire Yeeshabook); not for gameplay); but prevent linking
PrintKIType(kEnableEntireYeeshaBook);
PrintKIType(kKIOKDialogNoQuit); // display OK dialog in the KI without quiting afterwards
PrintKIType(kGZUpdated); // the GZ game was updated
PrintKIType(kGZInRange); // a GZ marker is in range
PrintKIType(kGZOutRange); // GZ markers are out of range
PrintKIType(kUpgradeKIMarkerLevel); // upgrade the KI Marker level (current 0 and 1)
PrintKIType(kKIShowMiniKI); // force the miniKI up
PrintKIType(kGZFlashUpdate); // flash an update without saving (for animation of GZFill in)
PrintKIType(kNoCommand);
info = xtl::format("Type: %s Str: %s User: %s(%d) Delay: %f Int: %d",
typeName,
kiMsg->GetString() != "" ? kiMsg->GetString().c_str() : "(nil)",
kiMsg->GetUser() ? kiMsg->GetUser() : "(nil)",
kiMsg->GetPlayerID(),
kiMsg->GetDelay(),
kiMsg->GetIntValue());
return true;
}
plClientMsg* clientMsg = plClientMsg::ConvertNoRef(msg);
if (clientMsg)
{
#define PrintType(type) if (clientMsg->GetClientMsgFlag() == plClientMsg::##type) info = #type;
PrintType(kLoadRoom);
PrintType(kLoadRoomHold);
PrintType(kUnloadRoom);
PrintType(kLoadNextRoom);
PrintType(kInitComplete);
PrintType(kDisableRenderScene);
PrintType(kEnableRenderScene);
PrintType(kQuit);
PrintType(kLoadAgeKeys);
PrintType(kReleaseAgeKeys);
switch (clientMsg->GetClientMsgFlag())
{
case plClientMsg::kLoadRoom:
case plClientMsg::kLoadRoomHold:
case plClientMsg::kUnloadRoom:
{
info += " - Pages: ";
const std::vector<plLocation>& locs = clientMsg->GetRoomLocs();
for (int i = 0; i < locs.size(); i++)
{
const plLocation& loc = locs[i];
const plPageInfo* pageInfo = plKeyFinder::Instance().GetLocationInfo(loc);
if (pageInfo)
info += xtl::format("%s-%s ", pageInfo->GetAge(), pageInfo->GetPage());
}
}
break;
case plClientMsg::kLoadAgeKeys:
case plClientMsg::kReleaseAgeKeys:
info += xtl::format(" - Age: %s", clientMsg->GetAgeName());
break;
}
return true;
}
plRefMsg* refMsg = plRefMsg::ConvertNoRef(msg);
if (refMsg)
{
const char* typeName = nil;
#define GetType(type) if (refMsg->GetContext() == plRefMsg::##type) typeName = #type;
GetType(kOnCreate);
GetType(kOnDestroy);
GetType(kOnRequest);
GetType(kOnRemove);
GetType(kOnReplace);
xtl::format(info, "Obj: %s RefType: %s", refMsg->GetRef()->GetKeyName(), typeName);
return true;
}
#endif // PLASMA_EXTERNAL_RELEASE
return false;
}

View File

@ -0,0 +1,59 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#ifndef pfDispatchLog_inc
#define pfDispatchLog_inc
#include "../pnDispatch/plDispatchLogBase.h"
#include "hsBitVector.h"
class plStatusLog;
class plDispatchLog : public plDispatchLogBase
{
private:
hsBitVector fIncludeTypes; // include/exclude list
UInt64 fStartTicks;
plStatusLog* fLog;
public:
plDispatchLog();
~plDispatchLog();
static void InitInstance();
void AddFilterType(UInt16 type);
void AddFilterExactType(UInt16 type);
void RemoveFilterType(UInt16 type);
void RemoveFilterExactType(UInt16 type);
void LogStatusBarChange(const char* name, const char* action);
void LogLongReceive(const char* keyname, const char* className, UInt32 clonePlayerID, plMessage* msg, float ms);
void DumpMsg(plMessage* msg, int numReceivers, int sendTimeMs, Int32 indent);
};
#endif // pfDispatchLog_inc

View File

@ -0,0 +1,451 @@
/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program 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 3 of the License, or
(at your option) any later version.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// pfGameConsoleCommands //
// //
// Set of console commands that are actually meant for implementing //
// gameplay. Simpler than Python, easier to implement for programmers, and //
// far lower level, but should be used with extreme caution. //
// //
// Why? Because unlike normal console commands, which will eventually be //
// disabled in the shipping product (thus no danger of any fan cracking //
// them), these WILL be in the finished product. Debugging hacks and temp //
// workarounds to new features are NOT to be implemented here. //
// //
// Because of their nature, all Game. console commands should be approved //
// by Brice before checkin. //
// //
// Preferred method of adding Game. commands: //
// 1. Implement in normal console command groups (Debug. if nothing //
// else) //
// 2. Get the command approved //
// 3. Once command is tested and approved and deemed both worthy and //
// bug-free, cut-and-paste the command into the Game. group //
// //
//////////////////////////////////////////////////////////////////////////////
#ifdef PLASMA_EXTERNAL_RELEASE
#define LIMIT_CONSOLE_COMMANDS 1
#endif
#include "pfConsoleCmd.h"
#include "pfConsole.h"
#include "plPipeline.h"
#include "plgDispatch.h"
#include "../plGImage/plMipmap.h"
#include "../plGImage/plTGAWriter.h"
#include "../pfMessage/pfGameGUIMsg.h"
#include "../../NucleusLib/inc/hsResMgr.h"
#include "../pfGameGUIMgr/pfGUICtrlGenerator.h"
#include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plAnimStage.h"
#include "../plAvatar/plAvBrainGeneric.h"
#include "../plAvatar/plAvBrainHuman.h"
#include "../plMessage/plAvatarMsg.h"
#include "../pnKeyedObject/plFixedKey.h"
#define PF_SANITY_CHECK( cond, msg ) { if( !( cond ) ) { PrintString( msg ); return; } }
//// DO NOT REMOVE!!!!
//// This is here so Microsoft VC won't decide to "optimize" this file out
//// DO NOT REMOVE!!!!
void pfConsoleCmdGroup::DummyJunior( void )
{
}
//// DO NOT REMOVE!!!!
//// plDoesFileExist //////////////////////////////////////////////////////////
// Utility function to determine whether the given file exists
static hsBool plDoesFileExist( const char *path )
{
hsUNIXStream stream;
if( !stream.Open( path, "rb" ) )
return false;
stream.Close();
return true;
}
//////////////////////////////////////////////////////////////////////////////
//// Game Group Commands /////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
PF_CONSOLE_GROUP( Game )
#ifndef LIMIT_CONSOLE_COMMANDS
PF_CONSOLE_CMD( Game, TakeScreenshot, "...", "Takes a shot of the current frame and saves it to the given file" )
{
hsAssert( pfConsole::GetPipeline() != nil, "Cannot use this command before pipeline initialization" );
plMipmap myMipmap;
char fileName[ 512 ];
UInt32 uniqueNumber;
if( numParams > 1 )
{
PrintString( "Too many parameters to TakeScreenshot" );
return;
}
else if( numParams == 1 )
strcpy( fileName, (char *)params[ 0 ] );
else
{
// Think up a filename
for( uniqueNumber = 1; uniqueNumber < 1000; uniqueNumber++ )
{
sprintf( fileName, "screen%03d.tga", uniqueNumber );
if( !plDoesFileExist( fileName ) )
break;
}
if( uniqueNumber == 1000 )
{
PrintString( "Out of filenames for TakeScreenshot" );
return;
}
}
if( !pfConsole::GetPipeline()->CaptureScreen( &myMipmap ) )
PrintString( "Error capturing screenshot" );
else
{
char str[ 512 ];
plTGAWriter::Instance().WriteMipmap( fileName, &myMipmap );
sprintf( str, "Screenshot written to '%s'.", fileName );
PrintString( str );
}
}
PF_CONSOLE_CMD( Game, LoadDialog, "string dlgName", "Loads the given GUI dialog into memory" )
{
plUoid lu( kGameGUIMgr_KEY );
plKey mgrKey = hsgResMgr::ResMgr()->FindKey( lu );
if( mgrKey )
{
pfGameGUIMsg *msg = TRACKED_NEW pfGameGUIMsg( mgrKey, pfGameGUIMsg::kLoadDialog );
msg->SetString( params[ 0 ] );
plgDispatch::MsgSend( msg );
}
}
PF_CONSOLE_CMD( Game, LoadLocalDialog, "string ageName, string dlgName", "Loads the given GUI dialog into memory" )
{
plUoid lu( kGameGUIMgr_KEY );
plKey mgrKey = hsgResMgr::ResMgr()->FindKey( lu );
if( mgrKey )
{
pfGameGUIMsg *msg = TRACKED_NEW pfGameGUIMsg( mgrKey, pfGameGUIMsg::kLoadDialog );
msg->SetString( params[ 1 ] );
msg->SetAge( params[ 0 ] );
plgDispatch::MsgSend( msg );
}
}
PF_CONSOLE_CMD( Game, ShowDialog, "string dlgName", "Shows the given GUI dialog" )
{
plUoid lu( kGameGUIMgr_KEY );
plKey mgrKey = hsgResMgr::ResMgr()->FindKey( lu );
if( mgrKey )
{
pfGameGUIMsg *msg = TRACKED_NEW pfGameGUIMsg( mgrKey, pfGameGUIMsg::kShowDialog );
msg->SetString( params[ 0 ] );
plgDispatch::MsgSend( msg );
}
}
PF_CONSOLE_CMD( Game, HideDialog, "string dlgName", "Hides the given GUI dialog" )
{
plUoid lu( kGameGUIMgr_KEY );
plKey mgrKey = hsgResMgr::ResMgr()->FindKey( lu );
if( mgrKey )
{
pfGameGUIMsg *msg = TRACKED_NEW pfGameGUIMsg( mgrKey, pfGameGUIMsg::kHideDialog );
msg->SetString( params[ 0 ] );
plgDispatch::MsgSend( msg );
}
}
PF_CONSOLE_CMD( Game, SwitchDialog, "string olddlgName, string newdlgName", "Hide olddlg and show newdlg" )
{
plUoid lu( kGameGUIMgr_KEY );
plKey mgrKey = hsgResMgr::ResMgr()->FindKey( lu );
if( mgrKey )
{
pfGameGUIMsg *msg = TRACKED_NEW pfGameGUIMsg( mgrKey, pfGameGUIMsg::kHideDialog );
msg->SetString( params[ 0 ] );
plgDispatch::MsgSend( msg );
pfGameGUIMsg *msg2 = TRACKED_NEW pfGameGUIMsg( mgrKey, pfGameGUIMsg::kShowDialog );
msg2->SetString( params[ 1 ] );
plgDispatch::MsgSend( msg2 );
}
}
PF_CONSOLE_SUBGROUP( Game, GUI )
#include "../pfGameGUIMgr/pfGUICtrlGenerator.h"
static hsColorRGBA sDynCtrlColor = hsColorRGBA().Set( 1, 1, 1, 1 ), sDynCtrlTextColor = hsColorRGBA().Set( 0, 0, 0, 1 );
PF_CONSOLE_CMD( Game_GUI, SetDynamicCtrlColor, "float bgRed, float bgGreen, float bgBlue, float textRed, float textGreen, float textBlue", "" )
{
sDynCtrlColor.Set( params[ 0 ], params[ 1 ], params[ 2 ], 1.f );
sDynCtrlTextColor.Set( params[ 3 ], params[ 4 ], params[ 5 ], 1.f );
}
PF_CONSOLE_CMD( Game_GUI, CreateRectButton, "string title, float x, float y, float width, float height, string command", "" )
{
pfGUICtrlGenerator::Instance().GenerateRectButton( params[ 0 ], params[ 1 ], params[ 2 ],
params[ 3 ], params[ 4 ],
params[ 5 ],
sDynCtrlColor, sDynCtrlTextColor );
}
PF_CONSOLE_CMD( Game_GUI, CreateRoundButton, "float x, float y, float radius, string command", "" )
{
pfGUICtrlGenerator::Instance().GenerateSphereButton( params[ 0 ], params[ 1 ], params[ 2 ],
params[ 3 ],
sDynCtrlColor );
}
PF_CONSOLE_CMD( Game_GUI, CreateDragBar, "float x, float y, float width, float height", "")
{
pfGUICtrlGenerator::Instance().GenerateDragBar( params[ 0 ], params[ 1 ], params[ 2 ], params[ 3 ], sDynCtrlColor );
}
PF_CONSOLE_CMD( Game_GUI, CreateDialog, "string name", "" )
{
pfGUICtrlGenerator::Instance().GenerateDialog( params[ 0 ] );
}
#endif
//#include "../pfKI/pfKI.h"
#include "../pfMessage/pfKIMsg.h"
PF_CONSOLE_CMD( Game, EnterChatMode, "", "Enters in-game chat mode" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kEnterChatMode);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIToggleMini, "", "Toggle between mini and big KI" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kMiniBigKIToggle);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIPutAway, "", "Put KI completely away" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIPutAway);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIChatPageUp, "", "Scroll chat display one page up" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kChatAreaPageUp);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIChatPageDown, "", "Scroll chat display one page down" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kChatAreaPageDown);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIChatToStart, "", "Scroll chat display to top of buffer" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kChatAreaGoToBegin);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIChatToEnd, "", "Scroll chat display to bottom of buffer" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kChatAreaGoToEnd);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KITakePicture, "", "Take picture with KI" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKITakePicture);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KICreateJournal, "", "Create journal note entry" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKICreateJournalNote);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIChatToggleFaded, "", "Toggle fade of chat display" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIToggleFade);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIChatToggleFadeEnable, "", "Toggle enable of chat fade" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIToggleFadeEnable);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIUpSizeFont, "", "Up size the KI font (chatarea)" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIUpSizeFont);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIDownSizeFont, "", "Down size the KI font (chatarea)" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIDownSizeFont);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIOpenYeeshaBook, "", "Open the player's Yeesha book" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIOpenYeehsaBook);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIOpenKI, "", "Open the KI a little at a time" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIOpenKI);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KIHelp, "", "Open the CCR help dialog" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKIShowCCRHelp);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KICreateMarker, "", "Create marker in the working marker folder" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKICreateMarker);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, KICreateMarkerFolder, "", "Create marker folder in current Age's journal folder" )
{
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kKICreateMarkerFolder);
plgDispatch::MsgSend( msg );
}
PF_CONSOLE_CMD( Game, SetChatFadeDelay, "float delayInSecs", "Sets the time in seconds before the chat text disappears" )
{
// pfKI::GetInstance()->SetChatFadeDelay( params[ 0 ] );
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kSetChatFadeDelay);
msg->SetDelay( params[0] );
plgDispatch::MsgSend( msg );
}
#include "../plAvatar/plArmatureMod.h"
PF_CONSOLE_CMD( Game, LimitAvatarLOD, "int newLOD", "Zero is (always) highest detail; 2 is (currently) lowest." )
{
int newLOD = params[0];
if(newLOD >= 0 && newLOD <= 2)
plArmatureLODMod::fMinLOD = newLOD;
}
PF_CONSOLE_SUBGROUP( Game, Emote) // Game.Emote.Shakefist
void Emote(const char *emotion, float fadeIn = 2.0, float fadeOut = 2.0)
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
AvatarEmote(avatar, emotion);
}
PF_CONSOLE_CMD( Game_Emote, Wave, "", "")
{
Emote("Wave", 4.0, 1.0);
}
PF_CONSOLE_CMD( Game_Emote, Sneeze, "", "")
{
Emote("Sneeze");
}
PF_CONSOLE_CMD( Game_Emote, Dance, "", "")
{
Emote("Dance");
}
PF_CONSOLE_CMD( Game_Emote, Laugh, "", "")
{
Emote("Laugh");
}
PF_CONSOLE_CMD( Game_Emote, Clap, "", "")
{
Emote("Clap", 4.0, 3.0);
}
PF_CONSOLE_CMD( Game_Emote, Talk, "", "")
{
Emote("Talk");
}
PF_CONSOLE_CMD( Game_Emote, Sit, "", "")
{
plArmatureMod *avatar = plAvatarMgr::GetInstance()->GetLocalAvatar();
PushSimpleMultiStage(avatar, "SitDownGround", "SitIdleGround", "SitStandGround", true, true, plAGAnim::kBodyLower, plAvBrainGeneric::kSitOnGround);
}
#ifndef PLASMA_EXTERNAL_RELEASE
PF_CONSOLE_CMD( Game, SetLocalClientAsAdmin, "bool enable", "Makes chat messages from this client appear as admin messages" )
{
// pfKI::GetInstance()->SetTextChatAdminMode( (bool)params[ 0 ] );
pfKIMsg* msg = TRACKED_NEW pfKIMsg(pfKIMsg::kSetTextChatAdminMode);
msg->SetFlags( params[0] ? pfKIMsg::kAdminMsg : 0 );
plgDispatch::MsgSend( msg );
}
#endif
#include "../pfConditional/plObjectInBoxConditionalObject.h"
PF_CONSOLE_CMD( Game, BreakVolumeSensors, "bool break", "reverts to old broken volume sensor logic" )
{
bool b = params[ 0 ];
plVolumeSensorConditionalObject::makeBriceHappyVar = !b;
}