networking

This commit is contained in:
2025-07-13 15:47:42 +03:00
parent f5b26be510
commit a9c28b8940
345 changed files with 142130 additions and 174 deletions

View File

@@ -0,0 +1,446 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Shared definitions for the communication between the server/client
//
// $NoKeywords: $
//=============================================================================
#ifndef SPACEWAR_H
#define SPACEWAR_H
// The Steamworks API's are modular, you can use some subsystems without using others
// When USE_GS_AUTH_API is defined you get the following Steam features:
// - Strong user authentication and authorization
// - Game server matchmaking
// - VAC cheat protection
// - Access to achievement/community API's
// - P2P networking capability
// Remove this define to disable using the native Steam authentication and matchmaking system
// You can use this as a sample of how to integrate your game without replacing an existing matchmaking system
// When you un-define USE_GS_AUTH_API you get:
// - Access to achievement/community API's
// - P2P networking capability
// You CANNOT use:
// - VAC cheat protection
// - Game server matchmaking
// as these function depend on using Steam authentication
#define USE_GS_AUTH_API
// Current game server version
#define SPACEWAR_SERVER_VERSION "1.0.0.0"
// UDP port for the spacewar server to listen on
#define SPACEWAR_SERVER_PORT 27015
// UDP port for the master server updater to listen on
#define SPACEWAR_MASTER_SERVER_UPDATER_PORT 27016
// How long to wait for a response from the server before resending our connection attempt
#define SERVER_CONNECTION_RETRY_MILLISECONDS 350
// How long to wait for a client to send an update before we drop its connection server side
#define SERVER_TIMEOUT_MILLISECONDS 5000
// Maximum packet size in bytes
#define MAX_SPACEWAR_PACKET_SIZE 1024*512
// Maximum number of players who can join a server and play simultaneously
#define MAX_PLAYERS_PER_SERVER 4
// Time to pause wait after a round ends before starting a new one
#define MILLISECONDS_BETWEEN_ROUNDS 4000
// How long photon beams live before expiring
#define PHOTON_BEAM_LIFETIME_IN_TICKS 1750
// How fast can photon beams be fired?
#define PHOTON_BEAM_FIRE_INTERVAL_TICKS 250
// Amount of space needed for beams per ship
#define MAX_PHOTON_BEAMS_PER_SHIP (PHOTON_BEAM_LIFETIME_IN_TICKS/PHOTON_BEAM_FIRE_INTERVAL_TICKS)
// Time to timeout a connection attempt in
#define MILLISECONDS_CONNECTION_TIMEOUT 30000
// How many times a second does the server send world updates to clients
#define SERVER_UPDATE_SEND_RATE 60
// How many times a second do we send our updated client state to the server
#define CLIENT_UPDATE_SEND_RATE 30
// How fast does the server internally run at?
#define MAX_CLIENT_AND_SERVER_FPS 86
template <typename T>
inline T WordSwap( T w )
{
uint16 temp;
temp = ((*((uint16 *)&w) & 0xff00) >> 8);
temp |= ((*((uint16 *)&w) & 0x00ff) << 8);
return *((T*)&temp);
}
template <typename T>
inline T DWordSwap( T dw )
{
uint32 temp;
temp = *((uint32 *)&dw) >> 24;
temp |= ((*((uint32 *)&dw) & 0x00FF0000) >> 8);
temp |= ((*((uint32 *)&dw) & 0x0000FF00) << 8);
temp |= ((*((uint32 *)&dw) & 0x000000FF) << 24);
return *((T*)&temp);
}
template <typename T>
inline T QWordSwap( T dw )
{
uint64 temp;
temp = *((uint64 *)&dw) >> 56;
temp |= ((*((uint64 *)&dw) & 0x00FF000000000000ull) >> 40);
temp |= ((*((uint64 *)&dw) & 0x0000FF0000000000ull) >> 24);
temp |= ((*((uint64 *)&dw) & 0x000000FF00000000ull) >> 8);
temp |= ((*((uint64 *)&dw) & 0x00000000FF000000ull) << 8);
temp |= ((*((uint64 *)&dw) & 0x0000000000FF0000ull) << 24);
temp |= ((*((uint64 *)&dw) & 0x000000000000FF00ull) << 40);
temp |= ((*((uint64 *)&dw) & 0x00000000000000FFull) << 56);
return *((T*)&temp);
}
#define LittleInt16( val ) ( val )
#define LittleWord( val ) ( val )
#define LittleInt32( val ) ( val )
#define LittleDWord( val ) ( val )
#define LittleQWord( val ) ( val )
#define LittleFloat( val ) ( val )
// Leaderboard names
#define LEADERBOARD_QUICKEST_WIN "Quickest Win"
#define LEADERBOARD_FEET_TRAVELED "Feet Traveled"
// Player colors
DWORD const g_rgPlayerColors[ MAX_PLAYERS_PER_SERVER ] =
{
D3DCOLOR_ARGB( 255, 255, 150, 150 ), // red
D3DCOLOR_ARGB( 255, 200, 200, 255 ), // blue
D3DCOLOR_ARGB( 255, 255, 204, 102 ), // orange
D3DCOLOR_ARGB( 255, 153, 255, 153 ), // green
};
// Enum for possible game states on the client
enum EClientGameState
{
k_EClientGameStartServer,
k_EClientGameActive,
k_EClientGameWaitingForPlayers,
k_EClientGameMenu,
k_EClientGameQuitMenu,
k_EClientGameExiting,
k_EClientGameInstructions,
k_EClientGameDraw,
k_EClientGameWinner,
k_EClientGameConnecting,
k_EClientGameConnectionFailure,
k_EClientFindInternetServers,
k_EClientStatsAchievements,
k_EClientCreatingLobby,
k_EClientInLobby,
k_EClientFindLobby,
k_EClientJoiningLobby,
k_EClientFindLANServers,
k_EClientRemoteStorage,
k_EClientLeaderboards,
k_EClientFriendsList,
k_EClientMinidump,
k_EClientClanChatRoom,
k_EClientWebCallback,
k_EClientMusic,
k_EClientWorkshop,
k_EClientHTMLSurface,
k_EClientInGameStore,
k_EClientRemotePlayInvite,
k_EClientRemotePlaySessions,
k_EClientOverlayAPI,
};
// Enum for possible game states on the server
enum EServerGameState
{
k_EServerWaitingForPlayers,
k_EServerActive,
k_EServerDraw,
k_EServerWinner,
k_EServerExiting,
};
#pragma pack( push, 1 )
// Data sent per photon beam from the server to update clients photon beam positions
struct ServerPhotonBeamUpdateData_t
{
void SetActive( bool bIsActive ) { m_bIsActive = bIsActive; }
bool GetActive() { return m_bIsActive; }
void SetRotation( float flRotation ) { m_flCurrentRotation = LittleFloat( flRotation ); }
float GetRotation() { return LittleFloat( m_flCurrentRotation ); }
void SetXVelocity( float flVelocity ) { m_flXVelocity = LittleFloat( flVelocity ); }
float GetXVelocity() { return LittleFloat( m_flXVelocity ); }
void SetYVelocity( float flVelocity ) { m_flYVelocity = LittleFloat( flVelocity ); }
float GetYVelocity() { return LittleFloat( m_flYVelocity ); }
void SetXPosition( float flPosition ) { m_flXPosition = LittleFloat( flPosition ); }
float GetXPosition() { return LittleFloat( m_flXPosition ); }
void SetYPosition( float flPosition ) { m_flYPosition = LittleFloat( flPosition ); }
float GetYPosition() { return LittleFloat( m_flYPosition ); }
private:
// Does the photon beam exist right now?
bool m_bIsActive;
// The current rotation
float m_flCurrentRotation;
// The current velocity
float m_flXVelocity;
float m_flYVelocity;
// The current position
float m_flXPosition;
float m_flYPosition;
};
// This is the data that gets sent per ship in each update, see below for the full update data
struct ServerShipUpdateData_t
{
void SetRotation( float flRotation ) { m_flCurrentRotation = LittleFloat( flRotation ); }
float GetRotation() { return LittleFloat( m_flCurrentRotation ); }
void SetRotationDeltaLastFrame( float flDelta ) { m_flRotationDeltaLastFrame = LittleFloat( flDelta ); }
float GetRotationDeltaLastFrame() { return LittleFloat( m_flRotationDeltaLastFrame ); }
void SetXAcceleration( float flAcceleration ) { m_flXAcceleration = LittleFloat( flAcceleration ); }
float GetXAcceleration() { return LittleFloat( m_flXAcceleration ); }
void SetYAcceleration( float flAcceleration ) { m_flYAcceleration = LittleFloat( flAcceleration ); }
float GetYAcceleration() { return LittleFloat( m_flYAcceleration ); }
void SetXVelocity( float flVelocity ) { m_flXVelocity = LittleFloat( flVelocity ); }
float GetXVelocity() { return LittleFloat( m_flXVelocity ); }
void SetYVelocity( float flVelocity ) { m_flYVelocity = LittleFloat( flVelocity ); }
float GetYVelocity() { return LittleFloat( m_flYVelocity ); }
void SetXPosition( float flPosition ) { m_flXPosition = LittleFloat( flPosition ); }
float GetXPosition() { return LittleFloat( m_flXPosition ); }
void SetYPosition( float flPosition ) { m_flYPosition = LittleFloat( flPosition ); }
float GetYPosition() { return LittleFloat( m_flYPosition ); }
void SetExploding( bool bIsExploding ) { m_bExploding = bIsExploding; }
bool GetExploding() { return m_bExploding; }
void SetDisabled( bool bIsDisabled ) { m_bDisabled = bIsDisabled; }
bool GetDisabled() { return m_bDisabled; }
void SetForwardThrustersActive( bool bActive ) { m_bForwardThrustersActive = bActive; }
bool GetForwardThrustersActive() { return m_bForwardThrustersActive; }
void SetReverseThrustersActive( bool bActive ) { m_bReverseThrustersActive = bActive; }
bool GetReverseThrustersActive() { return m_bReverseThrustersActive; }
void SetDecoration( int nDecoration ) { m_nShipDecoration = nDecoration; }
int GetDecoration() { return m_nShipDecoration; }
void SetWeapon( int nWeapon ) { m_nShipWeapon = nWeapon; }
int GetWeapon() { return m_nShipWeapon; }
void SetPower( int nPower ) { m_nShipPower = nPower; }
int GetPower() { return m_nShipPower; }
void SetShieldStrength( int nShieldStrength ) { m_nShieldStrength = nShieldStrength; }
int GetShieldStrength() { return m_nShieldStrength; }
void SetThrustersLevel( float fLevel ) { m_fThrusterLevel = fLevel; }
float GetThrustersLevel( ) { return m_fThrusterLevel; }
void SetTurnSpeed( float fSpeed ) { m_fTurnSpeed = fSpeed; }
float GetTurnSpeed( ) { return m_fTurnSpeed; }
ServerPhotonBeamUpdateData_t *AccessPhotonBeamData( int iIndex ) { return &m_PhotonBeamData[iIndex]; }
private:
// The current rotation of the ship
float m_flCurrentRotation;
// The delta in rotation for the last frame (client side interpolation will use this)
float m_flRotationDeltaLastFrame;
// The current thrust for the ship
float m_flXAcceleration;
float m_flYAcceleration;
// The current velocity for the ship
float m_flXVelocity;
float m_flYVelocity;
// The current position for the ship
float m_flXPosition;
float m_flYPosition;
// Is the ship exploding?
bool m_bExploding;
// Is the ship disabled?
bool m_bDisabled;
// Are the thrusters to be drawn?
bool m_bForwardThrustersActive;
bool m_bReverseThrustersActive;
// Decoration for this ship
int m_nShipDecoration;
// Weapon for this ship
int m_nShipWeapon;
// Power for this ship
int m_nShipPower;
int m_nShieldStrength;
// Photon beam positions and data
ServerPhotonBeamUpdateData_t m_PhotonBeamData[MAX_PHOTON_BEAMS_PER_SHIP];
// Thrust and rotation speed can be anlog when using a Steam Controller
float m_fThrusterLevel;
float m_fTurnSpeed;
};
// This is the data that gets sent from the server to each client for each update
struct ServerSpaceWarUpdateData_t
{
void SetServerGameState( EServerGameState eState ) { m_eCurrentGameState = LittleDWord( (uint32)eState ); }
EServerGameState GetServerGameState() { return (EServerGameState)LittleDWord( m_eCurrentGameState ); }
void SetPlayerWhoWon( uint32 iIndex ) { m_uPlayerWhoWonGame = LittleDWord( iIndex ); }
uint32 GetPlayerWhoWon() { return LittleDWord( m_uPlayerWhoWonGame ); }
void SetPlayerActive( uint32 iIndex, bool bIsActive ) { m_rgPlayersActive[iIndex] = bIsActive; }
bool GetPlayerActive( uint32 iIndex ) { return m_rgPlayersActive[iIndex]; }
void SetPlayerScore( uint32 iIndex, uint32 unScore ) { m_rgPlayerScores[iIndex] = LittleDWord(unScore); }
uint32 GetPlayerScore( uint32 iIndex ) { return LittleDWord(m_rgPlayerScores[iIndex]); }
void SetPlayerSteamID( uint32 iIndex, uint64 ulSteamID ) { m_rgPlayerSteamIDs[iIndex] = LittleQWord(ulSteamID); }
uint64 GetPlayerSteamID( uint32 iIndex ) { return LittleQWord(m_rgPlayerSteamIDs[iIndex]); }
ServerShipUpdateData_t *AccessShipUpdateData( uint32 iIndex ) { return &m_rgShipData[iIndex];}
private:
// What state the game is in
uint32 m_eCurrentGameState;
// Who just won the game? -- only valid when m_eCurrentGameState == k_EGameWinner
uint32 m_uPlayerWhoWonGame;
// which player slots are in use
bool m_rgPlayersActive[MAX_PLAYERS_PER_SERVER];
// what are the scores for each player?
uint32 m_rgPlayerScores[MAX_PLAYERS_PER_SERVER];
// array of ship data
ServerShipUpdateData_t m_rgShipData[MAX_PLAYERS_PER_SERVER];
// array of players steamids for each slot, serialized to uint64
uint64 m_rgPlayerSteamIDs[MAX_PLAYERS_PER_SERVER];
};
// This is the data that gets sent from each client to the server for each update
struct ClientSpaceWarUpdateData_t
{
void SetPlayerName( const char *pchName ) { strncpy_safe( m_rgchPlayerName, pchName, sizeof( m_rgchPlayerName ) ); }
const char *GetPlayerName() { return m_rgchPlayerName; }
void SetFirePressed( bool bIsPressed ) { m_bFirePressed = bIsPressed; }
bool GetFirePressed() { return m_bFirePressed; }
void SetTurnLeftPressed( bool bIsPressed ) { m_bTurnLeftPressed = bIsPressed; }
bool GetTurnLeftPressed() { return m_bTurnLeftPressed; }
void SetTurnRightPressed( bool bIsPressed ) { m_bTurnRightPressed = bIsPressed; }
bool GetTurnRightPressed() { return m_bTurnRightPressed; }
void SetForwardThrustersPressed( bool bIsPressed ) { m_bForwardThrustersPressed = bIsPressed; }
bool GetForwardThrustersPressed() { return m_bForwardThrustersPressed; }
void SetReverseThrustersPressed( bool bIsPressed ) { m_bReverseThrustersPressed = bIsPressed; }
bool GetReverseThrustersPressed() { return m_bReverseThrustersPressed; }
void SetDecoration( int nDecoration ) { m_nShipDecoration = nDecoration; }
int GetDecoration() { return m_nShipDecoration; }
void SetWeapon( int nWeapon ) { m_nShipWeapon = nWeapon; }
int GetWeapon() { return m_nShipWeapon; }
void SetPower( int nPower ) { m_nShipPower = nPower; }
int GetPower() { return m_nShipPower; }
void SetShieldStrength( int nShieldPower ) { m_nShieldStrength = nShieldPower; }
int GetShieldStrength() { return m_nShieldStrength; }
void SetThrustersLevel( float fLevel ) { m_fThrusterLevel = fLevel; }
float GetThrustersLevel( ) { return m_fThrusterLevel; }
void SetTurnSpeed( float fSpeed ) { m_fTurnSpeed = fSpeed; }
float GetTurnSpeed( ) { return m_fTurnSpeed; }
private:
// Key's which are done
bool m_bFirePressed;
bool m_bTurnLeftPressed;
bool m_bTurnRightPressed;
bool m_bForwardThrustersPressed;
bool m_bReverseThrustersPressed;
// Decoration for this ship
int m_nShipDecoration;
// Weapon for this ship
int m_nShipWeapon;
// Power for this ship
int m_nShipPower;
int m_nShieldStrength;
// Name of the player (needed server side to tell master server about)
// bugbug jmccaskey - Really lame to send this every update instead of event driven...
char m_rgchPlayerName[64];
// Thrust and rotation speed can be anlog when using a Steam Controller
float m_fThrusterLevel;
float m_fTurnSpeed;
};
#pragma pack( pop )
#endif // SPACEWAR_H