⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bloodservershell.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//
//	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 + -