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

📄 bloodservershell.cpp

📁 Blood 2全套源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
// ----------------------------------------------------------------------- //
//
// MODULE  : BloodServerShell.cpp
//
// PURPOSE : Blood's server shell - Implementation
//
// CREATED : 9/17/97
//
// ----------------------------------------------------------------------- //

#include "BloodServerShell.h"
#include "PlayerObj.h"
#include "cpp_server_de.h"
#include "PathMgr.h"
#include "ClientServerShared.h"
#include "FileCaching.h"
#include "ai_mgr.h"
#include "sparam.h"
#include "CameraObj.h"
#include "CVarTrack.h"
#include "CultistAI.h"

#include <windows.h>  // For DebugBreak
#include <winbase.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>


#define MAX_CLIENT_NAME_LENGTH		100
#define CLIENT_PING_UPDATE_RATE		7.5f
#define WAIT_TIME_FOR_LEVEL_SWITCH	7.5f

char g_szVarDoAutosave[]		= "GAME_DOAUTOSAVE";
char g_szVarRevisiting[]		= "GAME_REVISITING";
char g_szVarRestoring[]			= "GAME_RESTORING";
char g_szVarGotoStartpoint[]	= "GAME_GOTOSTARTPOINT";
char g_szVarWorldName[]			= "GAME_WORLDNAME";
char g_szVarDifficulty[]		= "GAME_DIFFICULTY";
char g_szVarGameType[]			= "GAME_GAMETYPE";
char g_szSavePath[]				= "Save\\Current\\";
char g_szAutoSaveFile[]			= "Auto.sav";
char g_szCurrentSaveFile[]		= "Current.sav";

DBOOL	g_bNextLevel = DFALSE;
DBOOL	g_bWaitToStartNextLevel = DFALSE;
DFLOAT	g_fWaitTimeForNextLevel = 0.0f;

CVarTrack	g_SayTrack;

extern	BOOL	g_bLevelChangeCharacter;
extern	int		g_nLevelChangeCharacter;


SETUP_SERVERSHELL()
DEFINE_CLASSES()

CBloodServerShell* g_pBloodServerShell = DNULL;

ServerShellDE* CreateServerShell(ServerDE *pServerDE)
{
	g_pServerDE = pServerDE;

	CBloodServerShell *pShell = new CBloodServerShell;

	g_pBloodServerShell = pShell;

	return (ServerShellDE*)pShell;
}


void DeleteServerShell(ServerShellDE *pInputShell)
{
	CBloodServerShell *pShell = (CBloodServerShell*)pInputShell;

	// Only set to NULL if we are deleting what we think is the current server shell..
	// gk
//	if (g_pBloodServerShell == pShell)
//		g_pBloodServerShell = DNULL;

	delete pShell;
}




// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBloodServerShell::CBloodServerShell()
//
//	PURPOSE:	Initialize
//
// ----------------------------------------------------------------------- //

CBloodServerShell::CBloodServerShell()
{
	memset(&m_GameInfo, 0, sizeof(NetGame));

	m_hstrStartPointName = DNULL;

#ifdef _ADD_ON
	m_bAddonLevel = DFALSE;
#endif

	SetUpdateBlood2Serv();

	ClearClientList();

	SetupGameInfo();

	m_bBlood2ServHosted = DFALSE;
	m_nCurLevel			 = 0;

	if (!m_VoiceMgr.IsInited())
	{
		m_VoiceMgr.Init(g_pServerDE);
	}

	g_SayTrack.Term();

	// Reset the goto-start-point game con var...
	g_pServerDE->SetGameConVar(g_szVarGotoStartpoint, "1");
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBloodServerShell::~CBloodServerShell()
//
//	PURPOSE:	Deallocate
//
// ----------------------------------------------------------------------- //

CBloodServerShell::~CBloodServerShell()
{
	if (!g_pServerDE) return;

	// Tell all clients that we are shutting down
	//HMESSAGEWRITE hMessage = g_pServerDE->StartMessage(NULL, SMSG_SERVERSHUTDOWN);
	//g_pServerDE->EndMessage(hMessage);

	if (m_hstrStartPointName)
		g_pServerDE->FreeString(m_hstrStartPointName);

	m_VoiceMgr.Term();

	g_SayTrack.Term();
}

/*
// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBloodServerShell::OnAddClient()
//
//	PURPOSE:	Add a client
//
// ----------------------------------------------------------------------- //

void CBloodServerShell::OnAddClient(HCLIENT hClient)
{
}
*/	

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBloodServerShell::OnRemoveClient()
//
//	PURPOSE:	Remove a client
//
// ----------------------------------------------------------------------- //

void CBloodServerShell::OnRemoveClient(HCLIENT hClient)
{
	CPlayerObj *pPlayer;
	ServerDE *pServerDE = GetServerDE();

	if(pPlayer = (CPlayerObj*)pServerDE->GetClientUserData(hClient))
	{
		pPlayer->SetClient(DNULL);
	}
}
	

// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBloodServerShell::OnClientEnterWorld()
//
//	PURPOSE:	Handle client entering the world
//
// ----------------------------------------------------------------------- //

BaseClass* CBloodServerShell::OnClientEnterWorld(HCLIENT hClient, void* pClientData, DDWORD dwClientDataLen)
{
	if (!g_pServerDE || !hClient) return DNULL;

	BaseClass* pObject  = DNULL;
	DBOOL bFoundClient = DFALSE;

	char szClientName[MAX_CLIENT_NAME_LENGTH];
	char szClientRefName[MAX_CLIENT_NAME_LENGTH];
	szClientName[0] = szClientRefName[0] = '\0';

	g_pServerDE->GetClientName(hClient, szClientName, MAX_CLIENT_NAME_LENGTH-1);

	// Search through the client refs to see if any of them match..
	HCLIENTREF hClientRef = g_pServerDE->GetNextClientRef(DNULL);
	while (hClientRef)
	{
		// See if this client reference is local or not...
		if (g_pServerDE->GetClientRefInfoFlags(hClientRef) & CIF_LOCAL)
		{
			bFoundClient = DTRUE;
		}

		// Determine if there is a reference to a client with the same name...
		if (!bFoundClient && g_pServerDE->GetClientRefName(hClientRef, szClientRefName, MAX_CLIENT_NAME_LENGTH-1))
		{
			if (szClientName[0] && szClientRefName[0])
			{
				if (_mbsicmp((const unsigned char*)szClientName, (const unsigned char*)szClientRefName) == 0)
				{
					bFoundClient = DTRUE;
				}
			}
		}

		// See if we found the right client...
		if (bFoundClient)
		{
			HOBJECT	hObject = g_pServerDE->GetClientRefObject(hClientRef);
			pObject = g_pServerDE->HandleToObject(hObject);

			if (pObject)
				RespawnPlayer(pObject, hClient);
			break;
		}

		hClientRef = g_pServerDE->GetNextClientRef(hClientRef);
	}

	// Add this client to the appropriate team...
	DWORD dwTeamID = TEAM_1;

	if (IsMultiplayerTeamBasedGame())
	{
		if (pClientData && dwClientDataLen == sizeof(NetClientData))
		{
			NetClientData* pNcd = (NetClientData*)pClientData;

			dwTeamID = pNcd->m_dwTeam;
		}

		if (dwTeamID == TEAM_AUTO)
		{
			CTeam* pTeam = m_TeamMgr.GetTeamWithLeastPlayers(TRUE);
			if (pTeam)
			{
				dwTeamID = pTeam->GetID();
			}
			else
			{
				if (IsRandomChance(50)) dwTeamID = TEAM_2;
				else dwTeamID = TEAM_1;
			}
		}

		DDWORD dwTransTeamID = m_TeamMgr.GetTeamTransID(g_pServerDE->GetClientID(hClient));
		CTeam* pTeam         = m_TeamMgr.GetTeam(dwTransTeamID);

		if (dwTransTeamID != TM_ID_NULL && pTeam)
		{
			dwTeamID = dwTransTeamID;
		}
	}

	m_TeamMgr.AddPlayer(dwTeamID, g_pServerDE->GetClientID(hClient));


	// See if we need to create a player (no matches found)...
	if (!pObject)
	{
		pObject = CreatePlayer(hClient);
		RespawnPlayer(pObject, hClient);
	}

	// Add this client to our local list...
	AddClientToList(hClient);

	// All done...
	return pObject;
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBloodServerShell::OnClientExitWorld()
//
//	PURPOSE:	Remove a client
//
// ----------------------------------------------------------------------- //

void CBloodServerShell::OnClientExitWorld(HCLIENT hClient)
{
	// Tell all clients..
	RemovePlayerMessage(hClient);

	// Remove this client from the team...
	m_TeamMgr.RemovePlayer(g_pServerDE->GetClientID(hClient));
	
	// Remove this client from our local list...
	RemoveClientFromList(hClient);
	SetUpdateBlood2Serv();

	// Remove the player object...
	CPlayerObj* pPlayer = (CPlayerObj*)g_pServerDE->GetClientUserData(hClient);
	if (pPlayer) 
	{
		pPlayer->DropFlag(DFALSE);
		g_pServerDE->RemoveObject(pPlayer->m_hObject);
	}

	g_pServerDE->SetClientUserData(hClient, DNULL);
}


// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBloodServerShell::OnMessage()
//
//	PURPOSE:	Handle messages
//
// ----------------------------------------------------------------------- //

void CBloodServerShell::OnMessage(HCLIENT hSender, DBYTE messageID, HMESSAGEREAD hMessage)
{
	if (!g_pServerDE) return;
	switch(messageID)
	{
		case CMSG_NEXTLEVEL:
		{
			g_bNextLevel = DTRUE;
			break;
		}
		case CMSG_WEAPON_FIRE:
		{
			void *pData = g_pServerDE->GetClientUserData(hSender);
			CPlayerObj* pPlayer = (CPlayerObj*)pData;
			if (pPlayer)
			{
				pPlayer->HandleWeaponFireMessage(hMessage);
			}
		}
		break;

		case CMSG_WEAPON_SOUND:
		{
			void *pData = g_pServerDE->GetClientUserData(hSender);
			CPlayerObj* pPlayer = (CPlayerObj*)pData;
			if (pPlayer)
			{
				pPlayer->HandleWeaponSoundMessage(hMessage);
			}
		}
		break;

		case CMSG_WEAPON_STATE:
		{
			void *pData = g_pServerDE->GetClientUserData(hSender);
			CPlayerObj* pPlayer = (CPlayerObj*)pData;
			if (pPlayer)
			{
				pPlayer->HandleWeaponStateMessage(hMessage);
			}
		}
		break;

		case CMSG_WEAPON_CHANGE:
		{
			void *pData = g_pServerDE->GetClientUserData(hSender);
			CPlayerObj* pPlayer = (CPlayerObj*)pData;
			if (pPlayer)
			{
				DBYTE nWeaponId = g_pServerDE->ReadFromMessageByte(hMessage);
				pPlayer->DoWeaponChange(nWeaponId);
			}
		}
		break;

		// Got a load world message
		case CMSG_LOADWORLD:
			{
				DBOOL bResult;
				bResult = LoadWorld(hMessage);
				// Acknowledge the load, good or bad
				HMESSAGEWRITE hMessage = g_pServerDE->StartMessage(NULL, SMSG_LOADWORLD_ACK);
				g_pServerDE->WriteToMessageByte(hMessage, (DBYTE)bResult);
				g_pServerDE->EndMessage(hMessage);
			}
			break;

		case CMSG_SAVEGAME:
			{
				HMESSAGEREAD hClientSaveData;
				CPlayerObj *pPlayerObj;
				char *pFilename = g_pServerDE->ReadFromMessageString(hMessage);
				DBOOL bSaveType = g_pServerDE->ReadFromMessageByte( hMessage );
				hClientSaveData = g_pServerDE->ReadFromMessageHMessageRead( hMessage );
	
				pPlayerObj = ( CPlayerObj * )g_pServerDE->GetClientUserData(hSender);
				if( pPlayerObj )
					pPlayerObj->SetClientSaveData( hClientSaveData );				
				

				if (bSaveType == SAVETYPE_CURRENT)
				{
					if (SaveGame(SAVETYPE_CURRENT, DTRUE, DTRUE))
					{	// Acknowledge a successful save
						HMESSAGEWRITE hMessage = g_pServerDE->StartMessage(NULL, SMSG_SAVEGAME_ACK);
						g_pServerDE->EndMessage(hMessage);
					}
				}
				else	// Do autosave
				{
					if (SaveGame(SAVETYPE_AUTO, DTRUE, DTRUE))
					{
						HMESSAGEWRITE hMessage = g_pServerDE->StartMessage(NULL, SMSG_SAVEGAME_ACK);
						g_pServerDE->EndMessage(hMessage);
					}
				}
			}
			break;

		case CMSG_DETACH_AI:
			{
				HOBJECT hObj = g_pServerDE->ReadFromMessageObject(hMessage);
			
				if(g_pServerDE->IsKindOf(g_pServerDE->GetObjectClass(hObj), g_pServerDE->GetClass("AI_Mgr")))
				{
					AI_Mgr* pAI = (AI_Mgr*)g_pServerDE->HandleToObject(hObj);
					pAI->DetachFromEnemy();
				}

				break;
			}

		case CMSG_ATTACH_ACK:
			{
				HOBJECT hObj = g_pServerDE->ReadFromMessageObject(hMessage);
			
				if(g_pServerDE->IsKindOf(g_pServerDE->GetObjectClass(hObj), g_pServerDE->GetClass("AI_Mgr")))
				{
					AI_Mgr* pAI = (AI_Mgr*)g_pServerDE->HandleToObject(hObj);
					pAI->ProceedToAttach();
				}

				break;
			}

		case CMSG_GAME_PAUSE:
		{
			DBOOL bPause = (DBOOL)g_pServerDE->ReadFromMessageByte(hMessage);

			DDWORD nFlags = g_pServerDE->GetServerFlags();
			if (bPause)
				nFlags |= SS_PAUSED;
			else
				nFlags &= ~SS_PAUSED;

			g_pServerDE->SetServerFlags(nFlags);
		}
		break;

		case CMSG_MULTIPLAYER_INIT:
		{
			CPlayerObj *pObj = (CPlayerObj*)g_pServerDE->GetClientUserData(hSender);
			if (pObj)
			{
				pObj->OnMessage(messageID, hMessage);

				// Tell other players that he's here
				AddPlayerMessage(DNULL, hSender);

				// tell new player about all current players (excluding himself)
				AddPlayersMessage(hSender);
				SetUpdateBlood2Serv();
			}
		}
		break;

		case CMSG_SINGLEPLAYER_INIT:
		{
			CPlayerObj *pObj = (CPlayerObj*)g_pServerDE->GetClientUserData(hSender);
			if (pObj)
			{
				pObj->OnMessage(messageID, hMessage);
			}
		}
		break;

		case CMSG_AUTOSAVE:
		{
#ifndef _DEMO
			// Autosave current situation, to be able to restart the world
			if (GetGameConVarValueFloat(g_szVarDoAutosave))
			{
				HMESSAGEWRITE hMessage = g_pServerDE->StartMessage(hSender, SMSG_DOAUTOSAVE);
				g_pServerDE->EndMessage(hMessage);

/*				if (SaveGame(SAVETYPE_AUTO, DTRUE, DTRUE))
				{
					HMESSAGEWRITE hMessage = g_pServerDE->StartMessage(NULL, SMSG_SAVEGAME_ACK);
					g_pServerDE->EndMessage(hMessage);
				}
*/
			}
#endif

		}
		break;

		default:	// Let the player handle it
		{
			CPlayerObj *pObj = (CPlayerObj*)g_pServerDE->GetClientUserData(hSender);
			if (pObj)
				pObj->OnMessage(messageID, hMessage);
		}
	}
}

			
// ----------------------------------------------------------------------- //
//
//	ROUTINE:	CBloodServerShell::OnCommandOn()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -