Game client codebase including: - CharacterActionControl: Character and creature management - GlobalScript: Network, items, skills, quests, utilities - RYLClient: Main client application with GUI and event handlers - Engine: 3D rendering engine (RYLGL) - MemoryManager: Custom memory allocation - Library: Third-party dependencies (DirectX, boost, etc.) - Tools: Development utilities 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
276 lines
10 KiB
C++
276 lines
10 KiB
C++
//----------------------------------------------------------------------------
|
|
// File: mazeserver.h
|
|
//
|
|
// Desc: see main.cpp
|
|
//
|
|
// Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
|
|
//-----------------------------------------------------------------------------
|
|
#ifndef _MAZESERVER_H
|
|
#define _MAZESERVER_H
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
#include "NetAbstract.h"
|
|
#include "SyncObjects.h"
|
|
#include "Maze.h"
|
|
#include "Random.h"
|
|
#include "Packets.h"
|
|
#include "Trig.h"
|
|
|
|
class CMaze;
|
|
struct ClientPosPacket;
|
|
|
|
#define SERVER_MAX_WIDTH 128
|
|
#define SERVER_MAX_HEIGHT 128
|
|
#define DEFAULT_MAZE_WIDTH 16
|
|
#define DEFAULT_MAZE_HEIGHT 16
|
|
#define DEFAULT_SEED 314159
|
|
#define LOCK_GRID_SIZE 16
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
struct PlayerData
|
|
{
|
|
DWORD dwID; // Client ID
|
|
DWORD NetID; // NetID for owning player (0 if none)
|
|
DWORD dwVersion; // Version of the owning player
|
|
BOOL bAllow; // If FALSE, then we should drop this player
|
|
|
|
// Links for the various lists
|
|
PlayerData* pNext; // Free/active PlayerData list (double link)
|
|
PlayerData* pPrevious;
|
|
PlayerData* pNextInCell; // Cell list (single link)
|
|
PlayerData* pNextInIDHashBucket; // ID hash bucket (single link)
|
|
|
|
FLOAT fLastDisplayTime;
|
|
FLOAT fLastCITime;
|
|
BOOL bActive;
|
|
|
|
float fPosX; // Floating point position
|
|
float fPosY;
|
|
WORD wCellX; // Coordinates of the cell this player is in
|
|
WORD wCellY; // or (0xffff,0xffff) for off-map
|
|
ANGLE aCameraYaw;
|
|
DWORD dwNumNearbyPlayers; // Number of nearby players
|
|
|
|
DWORD pad[4];
|
|
};
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
struct ServerCell
|
|
{
|
|
PlayerData* pFirstPlayerData;
|
|
};
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc:
|
|
//-----------------------------------------------------------------------------
|
|
class CMazeServer : public INetServer
|
|
{
|
|
public:
|
|
CMazeServer();
|
|
|
|
// From INetServer
|
|
void OnAddConnection( DWORD dwID );
|
|
HRESULT OnPacket( DWORD from, void* pData, DWORD dwSize );
|
|
void OnRemoveConnection( DWORD dwID );
|
|
void OnSessionLost( DWORD dwReason );
|
|
|
|
// Hook up to the network service
|
|
void SetOutboundServer( IOutboundServer* poutnet ) { m_pNet = poutnet; };
|
|
|
|
// Initialisation - need to hook up a maze object
|
|
HRESULT Init( BOOL bLocalLoopback, const CMaze* pmaze );
|
|
void Shutdown();
|
|
|
|
// Chance of server sending packets via reliable transport
|
|
void SetServerReliableRate( DWORD percent ) { m_dwServerReliableRate = percent; };
|
|
DWORD GetServerReliableRate() const { return m_dwServerReliableRate; };
|
|
|
|
// Timeout of server's packets
|
|
void SetServerTimeout( DWORD timeout ) { m_dwServerTimeout = timeout; };
|
|
DWORD GetServerTimeout() const { return m_dwServerTimeout; };
|
|
|
|
// Change of client sending packets via reliable transport. Setting this causes the server
|
|
// to propagate this setting to all currently connected clients
|
|
void SetClientReliableRate( DWORD percent );
|
|
DWORD GetClientReliableRate() const { return DWORD(m_ClientNetConfig.ubReliableRate); };
|
|
|
|
// Change client update rate. Setting this causes the server to propagate this setting to all
|
|
// currently connected clients
|
|
void SetClientUpdateRate( DWORD rate );
|
|
DWORD GetClientUpdateRate() const { return DWORD(m_ClientNetConfig.wUpdateRate); };
|
|
|
|
// Change client timeout. Setting this causes the server to propagate this setting to all
|
|
// currently connected clients
|
|
void SetClientTimeout( DWORD timeout );
|
|
DWORD GetClientTimeout() const { return DWORD(m_ClientNetConfig.wTimeout); };
|
|
|
|
// Change Client position pack size. Setting this causes the server to propagate this setting to all
|
|
// currently connected clients
|
|
void SetClientPackSize( DWORD size );
|
|
DWORD GetClientPackSize() const { return DWORD(m_ClientNetConfig.wClientPackSizeArray[m_ClientNetConfig.ubClientPackIndex]); };
|
|
|
|
// Change Server position pack size.
|
|
void SetServerPackSize( DWORD size );
|
|
DWORD GetServerPackSize() const { return DWORD(m_ClientNetConfig.wServerPackSizeArray[m_ClientNetConfig.ubServerPackIndex]); };
|
|
|
|
// How long the user wants to hold the Server's Dplay Threads
|
|
void SetServerThreadWait( DWORD threadwait ) { m_dwServerThreadWait = threadwait; };
|
|
DWORD GetServerThreadWait() const { return m_dwServerThreadWait; };
|
|
|
|
// How long the user wants to hold the Server's Dplay Threads
|
|
void SetClientThreadWait( DWORD threadwait );
|
|
DWORD GetClientThreadWait() const { return DWORD(m_ClientNetConfig.dwThreadWait); };
|
|
|
|
|
|
// Various commands
|
|
void DisplayConnectionInfo( DWORD dwID );
|
|
void DisplayNextConnectionInfo();
|
|
void PrintStats();
|
|
|
|
void SetLogLevel( DWORD dwLogLevel ) { m_dwLogLevel = dwLogLevel; }
|
|
DWORD GetLogLevel() { return m_dwLogLevel; }
|
|
|
|
DWORD GetNumPlayers() { return m_dwPlayerCount; }
|
|
|
|
protected:
|
|
BOOL m_bLocalLoopback;
|
|
IOutboundServer* m_pNet;
|
|
const CMaze* m_pMaze;
|
|
DWORD m_dwLogLevel;
|
|
DWORD m_dwWidth;
|
|
DWORD m_dwHeight;
|
|
CCriticalSection m_AddRemoveLock;
|
|
|
|
// A fixed sized grid of locks which we lay over the maze to control access to it
|
|
// We demand that the maze dimensions are a power-of-2 times the dimensions of this
|
|
// grid, and pre-store that power to allow fast translation
|
|
CLockArray<LOCK_GRID_SIZE,LOCK_GRID_SIZE> m_LockGrid;
|
|
DWORD m_dwMazeXShift;
|
|
DWORD m_dwMazeYShift;
|
|
void LockCell( DWORD x , DWORD y );
|
|
void UnlockCell( DWORD x , DWORD y );
|
|
void LockRange( DWORD x1 , DWORD y1 , DWORD x2 , DWORD y2 );
|
|
void UnlockRange( DWORD x1 , DWORD y1 , DWORD x2 , DWORD y2 );
|
|
void LockCellPair( DWORD x1 , DWORD y1 , DWORD x2 , DWORD y2 );
|
|
void UnlockCellPair( DWORD x1 , DWORD y1 , DWORD x2 , DWORD y2 );
|
|
CCriticalSection m_OffMapLock;
|
|
|
|
// The PlayerData lists
|
|
PlayerData m_PlayerDatas[MAX_PLAYER_OBJECTS];
|
|
PlayerData* m_pFirstActivePlayerData;
|
|
PlayerData* m_pFirstFreePlayerData;
|
|
DWORD m_dwActivePlayerDataCount;
|
|
DWORD m_dwPlayerDataUniqueValue;
|
|
CCriticalSection m_PlayerDataListLock;
|
|
|
|
// The player object locks
|
|
enum { NUM_PLAYER_OBJECT_LOCKS = 16 };
|
|
CCriticalSection m_PlayerDataLocks[NUM_PLAYER_OBJECT_LOCKS];
|
|
void LockPlayerData( PlayerData* pPlayerData ) { m_PlayerDataLocks[((pPlayerData-m_PlayerDatas) & (NUM_PLAYER_OBJECT_LOCKS-1))].Enter(); };
|
|
void UnlockPlayerData( PlayerData* pPlayerData ) { m_PlayerDataLocks[((pPlayerData-m_PlayerDatas) & (NUM_PLAYER_OBJECT_LOCKS-1))].Leave(); };
|
|
|
|
PlayerData* CreatePlayerData();
|
|
void DestroyPlayerData( PlayerData* pPlayerData );
|
|
|
|
// The cell array and the "off-map" cell.
|
|
ServerCell m_OffMapCell;
|
|
ServerCell m_Cells[SERVER_MAX_WIDTH][SERVER_MAX_HEIGHT];
|
|
|
|
// Remove playerdata from its cell
|
|
void RemovePlayerDataFromCell( PlayerData* pPlayerData );
|
|
|
|
// Unsafe versions of add/remove. Must have playerdata and cell locked when you call this
|
|
void UnsafeRemovePlayerDataFromCell( PlayerData* pPlayerData );
|
|
void UnsafeAddPlayerDataToCell( PlayerData* pPlayerData );
|
|
|
|
ServerCell* GetCell( PlayerData* pPlayerData )
|
|
{
|
|
if ( pPlayerData->wCellX == 0xffff )
|
|
return &m_OffMapCell;
|
|
else
|
|
return &m_Cells[pPlayerData->wCellY][pPlayerData->wCellX];
|
|
};
|
|
|
|
void HandleClientPosPacket( DWORD dwFrom, ClientPosPacket* pPacket );
|
|
void HandleClientVersionPacket( DWORD dwFrom, ClientVersionPacket* pClientVersionPack );
|
|
void HandleUnknownPacket( DWORD dwFrom, ClientPacket* pClientPack, DWORD size );
|
|
|
|
BOOL IsValidPackSize( DWORD wSize );
|
|
BOOL IsClientVersionSupported( DWORD dwClientVersion );
|
|
|
|
DWORD m_dwPlayerCount;
|
|
|
|
CCriticalSection m_csThreadCountLock;
|
|
WORD m_wActiveThreadCount;
|
|
WORD m_wMaxThreadCount;
|
|
FLOAT m_fAvgThreadCount;
|
|
FLOAT m_fAvgThreadTime;
|
|
FLOAT m_fMaxThreadTime;
|
|
|
|
DWORD m_dwPeakPlayerCount;
|
|
|
|
// Hashing DPIDs to PlayerData pointers
|
|
void SetPlayerDataForID( DWORD dwID, PlayerData* pPlayerData );
|
|
PlayerData* GetPlayerDataForID( DWORD dwID );
|
|
void RemovePlayerDataID( PlayerData* pPlayerData );
|
|
DWORD IDHash( DWORD dwID );
|
|
enum { NUM_ID_HASH_BUCKETS = 1024 };
|
|
enum { NUM_ID_HASH_BUCKET_LOCKS = 16 };
|
|
PlayerData* m_pstIDHashBucket[NUM_ID_HASH_BUCKETS];
|
|
CCriticalSection m_IDHashBucketLocks[NUM_ID_HASH_BUCKET_LOCKS];
|
|
|
|
// Random number generator
|
|
CRandom m_Rand;
|
|
|
|
// Send packet wrapper
|
|
HRESULT SendPacket( DWORD dwTo, void* pData, DWORD dwSize, BOOL bReliable, DWORD dwTimeout );
|
|
void SendConfigPacketToAll( ServerConfigPacket* pPacket );
|
|
|
|
// Network configuration parameters
|
|
DWORD m_dwServerReliableRate;
|
|
DWORD m_dwServerTimeout;
|
|
DWORD m_dwServerThreadWait;
|
|
|
|
ClientNetConfig m_ClientNetConfig;
|
|
CCriticalSection m_ClientNetConfigLock;
|
|
};
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Name:
|
|
// Desc: This function is called by the server to output informational text.
|
|
// In the client it should probably just be a dummy function, in the server
|
|
// it should probably just spew out to the console
|
|
//-----------------------------------------------------------------------------
|
|
enum ServerBufferType { SLINE_PROMPT, SLINE_INPUT, SLINE_LOG, SLINE_CMD };
|
|
void ConsolePrintf( ServerBufferType enumLineType, const TCHAR* fmt , ... );
|
|
|
|
|
|
|
|
#endif
|