📄 bloodservershell.cpp
字号:
//
// PURPOSE: Handle commands
//
// ----------------------------------------------------------------------- //
void CBloodServerShell::OnCommandOn(HCLIENT hClient, int command)
{
CPlayerObj *pObj = (CPlayerObj*)g_pServerDE->GetClientUserData(hClient);
if (pObj)
pObj->OnCommandOn(command);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CBloodServerShell::PreStartWorld()
//
// PURPOSE: Handle stuff that needs to happen before a world is loaded.
//
// ----------------------------------------------------------------------- //
void CBloodServerShell::PreStartWorld(DBOOL bSwitchingWorlds)
{
// Setup the teams for multiplayer
m_TeamMgr.Term();
m_TeamMgr.Init();
m_TeamMgr.AddTeam(TEAM_1, "TEAM1");
m_TeamMgr.AddTeam(TEAM_2, "TEAM2");
// Setup the game info
SetupGameInfo();
g_bNextLevel = DFALSE;
// Reset global camera pointer
g_hActiveCamera = DNULL;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CBloodServerShell::PostStartWorld()
//
// PURPOSE: Perform an autosave after the world is loaded
//
// ----------------------------------------------------------------------- //
void CBloodServerShell::PostStartWorld()
{
// Build the list of AI paths for this world...
m_PathMgr.BuildPathList();
// Init the voice manager if necessary...
if (!m_VoiceMgr.IsInited())
{
m_VoiceMgr.Init(g_pServerDE);
}
m_VoiceMgr.StopAll();
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CBloodServerShell::ConsoleMessage()
//
// PURPOSE: Handle messages
//
// ----------------------------------------------------------------------- //
void CBloodServerShell::ConsoleMessage(HCLIENT hClient, char *msg)
{
HMESSAGEWRITE hMsg;
hMsg = g_pServerDE->StartMessage(hClient, SMSG_CONSOLEMESSAGE);
g_pServerDE->WriteToMessageString(hMsg, msg);
g_pServerDE->EndMessage(hMsg);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CBloodServerShell::AddPlayerMessage()
//
// PURPOSE: Sends an AddPlayer message to all clients when a new player
// comes in.
//
// ----------------------------------------------------------------------- //
void CBloodServerShell::AddPlayerMessage(HCLIENT hDestClient, HCLIENT hNewPlayerClient)
{
if (!hNewPlayerClient || !g_pServerDE) return;
HMESSAGEWRITE hMsg;
CPlayerObj *pObj = (CPlayerObj*)g_pServerDE->GetClientUserData(hNewPlayerClient);
if (pObj)
{
HSTRING hstrName = pObj->GetPlayerName();
DDWORD dwClientID = g_pServerDE->GetClientID(hNewPlayerClient);
// Send the message to hDestClient, if it's NULL, all clients get this message
hMsg = g_pServerDE->StartMessage(hDestClient, SMSG_ADDPLAYER);
g_pServerDE->WriteToMessageHString(hMsg, hstrName);
g_pServerDE->WriteToMessageDWord(hMsg, dwClientID);
g_pServerDE->WriteToMessageByte(hMsg, pObj->GetCharacter());
g_pServerDE->WriteToMessageFloat(hMsg, (DFLOAT) pObj->GetFrags());
g_pServerDE->WriteToMessageByte(hMsg, (DBYTE)pObj->GetTeamID());
g_pServerDE->EndMessage2(hMsg, MESSAGE_GUARANTEED | MESSAGE_NAGGLE);
}
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CBloodServerShell::AddPlayersMessage()
//
// PURPOSE: Iterates through the client list and sends a SMSG_ADDPLAYER
// message for each to hClient.
//
// ----------------------------------------------------------------------- //
void CBloodServerShell::AddPlayersMessage(HCLIENT hClient)
{
if (!hClient || !g_pServerDE) return;
for (int i = 0; i < MAX_CLIENTS; i++)
{
if (m_aClients[i] && hClient != m_aClients[i])
{
AddPlayerMessage(hClient, m_aClients[i]);
}
}
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CBloodServerShell::RemovePlayerMessage()
//
// PURPOSE: Sends an RemovePlayer message to all clients when a player
// leaves.
//
// ----------------------------------------------------------------------- //
void CBloodServerShell::RemovePlayerMessage(HCLIENT hClient)
{
if (!hClient || !g_pServerDE) return;
DDWORD dwClientID = g_pServerDE->GetClientID(hClient);
// Send the message to all clients
HMESSAGEWRITE hMsg = g_pServerDE->StartMessage(DNULL, SMSG_REMOVEPLAYER);
g_pServerDE->WriteToMessageDWord(hMsg, dwClientID);
// [blg] g_pServerDE->EndMessage2(hMsg, MESSAGE_GUARANTEED | MESSAGE_NAGGLE);
g_pServerDE->EndMessage(hMsg);
}
void CBloodServerShell::FragStatus()
{
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CBloodServerShell::CreatePlayer()
//
// PURPOSE: Create the player object, and associate it with the client.
//
// ----------------------------------------------------------------------- //
BaseClass* CBloodServerShell::CreatePlayer(HCLIENT hClient)
{
if (!g_pServerDE) return DNULL;
ObjectCreateStruct ocStruct;
INIT_OBJECTCREATESTRUCT(ocStruct);
ROT_INIT(ocStruct.m_Rotation);
VEC_INIT(ocStruct.m_Pos);
ocStruct.m_Flags = 0;
HCLASS hClass = g_pServerDE->GetClass("CPlayerObj");
BaseClass* pClass = NULL;
if (hClass)
{
pClass = g_pServerDE->CreateObject(hClass, &ocStruct);
if (pClass)
{
CPlayerObj* pPlayer = (CPlayerObj*)pClass;
pPlayer->SetClient(hClient);
g_pServerDE->SetClientUserData(hClient, (void *)pClass);
pPlayer->Respawn();
// pPlayer->GoToStartPoint();
pPlayer->UpdateTeamID();
}
}
return pClass;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CBloodServerShell::RespawnPlayer()
//
// PURPOSE: Respawn the player object
//
// ----------------------------------------------------------------------- //
void CBloodServerShell::RespawnPlayer(BaseClass* pBaseObject, HCLIENT hClient)
{
if (!pBaseObject || !hClient) return;
CPlayerObj* pPlayer = (CPlayerObj*)pBaseObject;
pPlayer->SetClient(hClient);
g_pServerDE->SetClientUserData(hClient, (void *)pPlayer);
// If this is a multiplayer game wait until MULTIPLAYER_INIT message
// to respawn the player...
DBYTE nMessage = SMSG_PLAYERINIT_MULTIPLAYER;
if (GetGameType() == GAMETYPE_SINGLE)
{
nMessage = SMSG_PLAYERINIT_SINGLEPLAYER;
}
HMESSAGEWRITE hWrite = g_pServerDE->StartMessage(hClient, nMessage);
// If this is a multiplayer game, send some game info too...
if (nMessage == SMSG_PLAYERINIT_MULTIPLAYER)
{
g_pServerDE->WriteToMessageByte(hWrite, m_GameInfo.m_byType);
g_pServerDE->WriteToMessageByte(hWrite, m_GameInfo.m_bFriendlyFire);
g_pServerDE->WriteToMessageByte(hWrite, m_GameInfo.m_bNegTeamFrags);
g_pServerDE->WriteToMessageByte(hWrite, m_GameInfo.m_bOnlyFlagScores);
g_pServerDE->WriteToMessageByte(hWrite, m_GameInfo.m_bOnlyGoalScores);
}
// End the message...
g_pServerDE->EndMessage2(hWrite, MESSAGE_GUARANTEED | MESSAGE_NAGGLE);
// Either a new level or restoring a previously visited level, so go to the startpoint
if (IsMultiplayerGame() || GetGameConVarValueFloat(g_szVarGotoStartpoint))
{
pPlayer->GoToStartPoint();
}
// Restoring a save, so don't change player and tell the client where to point the camera
else
{
pPlayer->SendMessageToClient(SMSG_FORCEROTATION);
pPlayer->SendMessageToClient(SMSG_EYELEVEL);
}
// Reset the goto-start-point game con var...
g_pServerDE->SetGameConVar(g_szVarGotoStartpoint, "1");
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CBloodServerShell::SetStartpointName()
//
// PURPOSE: Sets the name of the next startpoint.
//
// ----------------------------------------------------------------------- //
void CBloodServerShell::SetStartPointName(HSTRING hString)
{
if (!hString || !g_pServerDE) return;
if (m_hstrStartPointName)
{
g_pServerDE->FreeString(m_hstrStartPointName);
}
m_hstrStartPointName = g_pServerDE->CopyString(hString);
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CBloodServerShell::LoadWorld()
//
// PURPOSE: handles the LOADWORLD message
//
// ----------------------------------------------------------------------- //
DBOOL CBloodServerShell::LoadWorld(HMESSAGEREAD hMessage)
{
char szPath[MAX_PATH];
char *pFilename = g_pServerDE->ReadFromMessageString(hMessage);
DBYTE nGameType = g_pServerDE->ReadFromMessageByte(hMessage);
DBYTE nLoadType = g_pServerDE->ReadFromMessageByte(hMessage);
DBYTE nDifficulty = g_pServerDE->ReadFromMessageByte(hMessage);
CultistAI::ResetStatics(); // fix a wierd clown animation bug
if (!pFilename || _mbstrlen(pFilename) <= 0) return DFALSE;
DRESULT res = DE_OK;
DBOOL bRestoring = DFALSE;
DBOOL bRestoringKeepAlive = DFALSE;
DBOOL bRevisiting = DFALSE;
// Remove leading slashes..
while(*pFilename == '\\' || *pFilename == '/')
pFilename++;
// Init the voice manager if necessary...
if (!m_VoiceMgr.IsInited())
{
m_VoiceMgr.Init(g_pServerDE);
}
m_VoiceMgr.StopAll();
// // Current world name
// char *pOldWorld = g_pServerDE->GetVarValueString(g_pServerDE->GetGameConVar(g_szVarWorldName));
// Set console variables
// Save the filename in a console var for later use.
g_pServerDE->SetGameConVar(g_szVarWorldName, szPath);
#ifdef _ADDON
char sUpr[256];
strncpy(sUpr, pFilename, 255);
strupr(sUpr);
if (strstr(sUpr, "WORLDS_AO"))
{
strncpy(szPath, pFilename, MAX_PATH);
m_bAddonLevel = DTRUE;
}
else
{
_mbscpy((unsigned char*)szPath, (const unsigned char*)"Worlds\\");
_mbscat((unsigned char*)szPath, (const unsigned char*)pFilename);
m_bAddonLevel = DFALSE;
}
#else
_mbscpy((unsigned char*)szPath, (const unsigned char*)"Worlds\\");
_mbscat((unsigned char*)szPath, (const unsigned char*)pFilename);
#endif
// Set console variables
// Save the filename in a console var for later use.
g_pServerDE->SetGameConVar(g_szVarWorldName, szPath);
// If this is a brand-new game, set various stuff
if (nLoadType == LOADTYPE_NEW_GAME)
{
// Set difficulty level
SetGameInfo(nGameType, nDifficulty);
}
// Restoring an autosave game
if (nLoadType == LOADTYPE_RESTOREAUTOSAVE)
{
pFilename = g_szAutoSaveFile; // Restore from "auto.sav" file
bRestoring = DTRUE;
}
// Restoring a saved game
else if (nLoadType == LOADTYPE_RESTORESAVE)
{
bRestoring = DTRUE;
}
// New level, so we need to save the current world and the player data
else if (nLoadType == LOADTYPE_NEW_LEVEL)
{
// Check if this is an add-on level that wants a player change
DoLevelChangeCharacterCheck(pFilename);
// Save the player data
KeepAliveSave();
bRestoringKeepAlive = DTRUE;
// Save the current world sans players or console, in case we want to go back
/* Not doing this, so I'll just comment it out for now.. (Greg 10/5)
if (pOldWorld)
SaveGame(pOldWorld, DFALSE, DFALSE);
// See if there is a save file for this level
char szSavePath[MAX_PATH];
_mbscpy((unsigned char*)szSavePath, (const unsigned char*)g_szSavePath);
_mbscat((unsigned char*)szSavePath, (const unsigned char*)pFilename);
_mbscat((unsigned char*)szSavePath, (const unsigned char*)".sav");
// See if there is a save file for this level
if (int fhl = _open(szSavePath, _O_RDONLY) != -1)
{
_close(fhl);
bRevisiting = DTRUE;
bRestoring = DTRUE;
}
*/
}
if (pFilename && _mbstrlen(pFilename))
{
DDWORD dwLoadFlags = 0;
// Set load flags
if (!bRestoring)
dwLoadFlags |= LOADWORLD_LOADWORLDOBJECTS;
// if (pOldWorld && _mbsicmp((const unsigned char*)pOldWorld, (const unsigned char*)szPath) == 0) // loading same world as current, don't reload geometry
// {
dwLoadFlags |= LOADWORLD_NORELOADGEOMETRY;
// g_pServerDE->DebugOut("Not loading geometry");
// }
dwLoadFlags |= LOADWORLD_NORELOADGEOMETRY;
res = g_pServerDE->LoadWorld(szPath, dwLoadFlags);
if (res != DE_OK)
{
g_pServerDE->BPrint("Error loading world %s: %d", pFilename, res);
return DFALSE;
}
}
// Restoring a game - Restore player position too.
if (bRestoring)
{
if (nLoadType == LOADTYPE_RESTOREAUTOSAVE)
RestoreGame(SAVETYPE_AUTO);
else
RestoreGame(SAVETYPE_CURRENT);
}
// Restoring saved player data
if (bRestoringKeepAlive)
{
KeepAliveLoad();
}
// All types start at a startpoint if not restoring, or if restoring a previous visited level
g_pServerDE->SetGameConVar(g_szVarGotoStartpoint, (!bRestoring || bRestoringKeepAlive) ? "1" : "0");
// Set this if we are revisiting a world
g_pServerDE->SetGameConVar(g_szVarRevisiting, bRevisiting ? "1" : "0");
// Autosave if not restoring (new level), or if we are revisiting.
// Set this flag so we know whether to autosave later
g_pServerDE->SetGameConVar(g_szVarDoAutosave, (!bRestoring || bRevisiting) ? "1" : "0");
// Now run the world
res = g_pServerDE->RunWorld();
if (res != DE_OK)
{
g_pServerDE->BPrint("Error running world %s: %d", pFilename, res);
return DFALSE;
}
return DTRUE;
}
// ----------------------------------------------------------------------- //
//
// ROUTINE: CBloodServerShell::SaveGame()
//
// PURPOSE: Saves the state of the current world
//
// ----------------------------------------------------------------------- //
DBOOL CBloodServerShell::SaveGame(DBYTE bySaveType, DBOOL bSavePlayers, DBOOL bSaveConsole)
{
DBOOL bRet = DFALSE;
if (!g_pServerDE)
return DFALSE;
char szSavePath[MAX_PATH];
_mbscpy((unsigned char*)szSavePath, (const unsigned char*)g_szSavePath);
if (bySaveType == SAVETYPE_CURRENT)
_mbscat((unsigned char*)szSavePath, (const unsigned char*)g_szCurrentSaveFile);
else if (bySaveType == SAVETYPE_AUTO)
_mbscat((unsigned char*)szSavePath, (const unsigned char*)g_szAutoSaveFile);
else
return DFALSE;
// Make a list of savable objects
ObjectList* pObjectList = g_pServerDE->CreateObjectList();
// Loop through active objects
HOBJECT hObj = g_pServerDE->GetNextObject(DNULL);
while (hObj)
{
DDWORD dwFlags = g_pServerDE->GetObjectUserFlags(hObj);
// Can this object be saved?
if ((dwFlags & USRFLG_SAVEABLE) && (bSavePlayers || !IsPlayer(hObj)))
{
ObjectLink *ol = g_pServerDE->AddObjectToList(pObjectList, hObj);
ol->m_hObject = hObj;
}
hObj = g_pServerDE->GetNextObject(hObj);
}
// And inactive objects
hObj = g_pServerDE->GetNextInactiveObject(DNULL);
while (hObj)
{
DDWORD dwFlags = g_pServerDE->GetObjectUserFlags(hObj);
// Can this object be saved?
if ((dwFlags & USRFLG_SAVEABLE) && (bSavePlayers || !IsPlayer(hObj)))
{
ObjectLink *ol = g_pServerDE->AddObjectToList(pObjectList, hObj);
ol->m_hObject = hObj;
}
hObj = g_pServerDE->GetNextInactiveObject(hObj);
}
DDWORD dwSaveFlags = 0;
if (bSaveConsole)
dwSaveFlags |= SAVEOBJECTS_SAVEGAMECONSOLE | SAVEOBJECTS_SAVEPORTALS;
if (g_pServerDE->SaveObjects(szSavePath, pObjectList, 0, dwSaveFlags) == DE_OK)
bRet = DTRUE;
g_pServerDE->RelinquishList(pObjectList);
return bRet;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -