This commit is contained in:
Riley Labrecque
2014-01-29 12:53:34 +02:00
commit 1383b358e4
85 changed files with 12107 additions and 0 deletions
+18
View File
@@ -0,0 +1,18 @@
This is the Steamworks SDK v1.0
================================================================
Copyright © 1996-2008, Valve Corporation, All rights reserved.
================================================================
Welcome to the Steamworks SDK. For documentation please see our partner
website at: http://partner.steamgames.com.
Revision History:
v1.0:
- Initial Steamworks SDK release
+16
View File
@@ -0,0 +1,16 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Base class for various game menu screens
//
// $NoKeywords: $
//=============================================================================
#include "stdafx.h"
#include "BaseMenu.h"
// Static data
HGAMEFONT g_hMenuFont = 0;
uint64 g_ulLastReturnKeyTick = 0;
uint64 g_ulLastKeyDownTick = 0;
uint64 g_ulLastKeyUpTick = 0;
+237
View File
@@ -0,0 +1,237 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Base class for various game menu screens
//
// $NoKeywords: $
//=============================================================================
#ifndef BASEMENU_H
#define BASEMENU_H
#include <string>
#include <vector>
#include "GameEngine.h"
#include "SpaceWar.h"
#include "SpaceWarClient.h"
#define MENU_FONT_HEIGHT 24
#define MENU_ITEM_PADDING 12
extern HGAMEFONT g_hMenuFont;
extern uint64 g_ulLastReturnKeyTick;
extern uint64 g_ulLastKeyDownTick;
extern uint64 g_ulLastKeyUpTick;
template <class T> class CBaseMenu
{
public:
// Typedef for menu items
typedef std::pair<std::string, T> MenuItem_t;
// Constructor
CBaseMenu( CGameEngine *pGameEngine )
{
m_pGameEngine = pGameEngine;
m_uSelectedItem = 0;
m_bSelectionPushed = false;
if ( !g_hMenuFont )
{
g_hMenuFont = pGameEngine->HCreateFont( MENU_FONT_HEIGHT, FW_BOLD, false, "Arial" );
if ( !g_hMenuFont )
OutputDebugString( "Menu font was not created properly, text won't draw\n" );
}
}
// Sets a heading for the menu
void SetHeading( const char *pchHeading )
{
m_sHeading = pchHeading;
}
// Clear all menu entries
void ClearMenuItems()
{
m_VecMenuItems.clear();
m_uSelectedItem = 0;
}
// Add a menu item to the menu
void AddMenuItem( MenuItem_t item )
{
m_VecMenuItems.push_back( item );
}
void PushSelectedItem()
{
if ( m_VecMenuItems.size() )
{
m_bSelectionPushed = true;
m_selection = m_VecMenuItems[m_uSelectedItem].second;
}
}
void PopSelectedItem()
{
if ( m_bSelectionPushed )
{
m_bSelectionPushed = false;
// find the item and set it as selected if it exists
for ( unsigned int i = 0; i < m_VecMenuItems.size(); i++ )
{
if ( !memcmp( &m_VecMenuItems[i].second, &m_selection, sizeof( m_selection ) ) )
{
m_uSelectedItem = i;
break;
}
}
}
}
// Run a frame + render
void RunFrame()
{
// Note: The below code uses globals that are shared across all menus to avoid double
// key press registration, this is so that when you do something like hit return in the pause
// menu to "go back to main menu" you don't end up immediately registering a return in the
// main menu afterwards.
// check if the enter key is down, if it is take action
if ( m_pGameEngine->BIsKeyDown( VK_RETURN ) )
{
uint64 ulCurrentTickCount = m_pGameEngine->GetGameTickCount();
if ( ulCurrentTickCount - 150 > g_ulLastReturnKeyTick )
{
g_ulLastReturnKeyTick = ulCurrentTickCount;
if ( m_uSelectedItem >= 0 && m_uSelectedItem < m_VecMenuItems.size() )
{
SpaceWarClient()->OnMenuSelection( m_VecMenuItems[m_uSelectedItem].second );
return;
}
}
}
// Check if we need to change the selected menu item
else if ( m_pGameEngine->BIsKeyDown( VK_DOWN ) )
{
uint64 ulCurrentTickCount = m_pGameEngine->GetGameTickCount();
if ( ulCurrentTickCount - 150 > g_ulLastKeyDownTick )
{
g_ulLastKeyDownTick = ulCurrentTickCount;
if ( m_uSelectedItem < m_VecMenuItems.size() - 1 )
m_uSelectedItem++;
}
}
else if ( m_pGameEngine->BIsKeyDown( VK_UP ) )
{
uint64 ulCurrentTickCount = m_pGameEngine->GetGameTickCount();
if ( ulCurrentTickCount - 250 > g_ulLastKeyUpTick )
{
g_ulLastKeyUpTick = ulCurrentTickCount;
if ( m_uSelectedItem > 0 )
m_uSelectedItem--;
}
}
Render();
}
// Render the menu
virtual void Render()
{
const int32 iMaxMenuItems = 13;
int32 iNumItems = (int32)m_VecMenuItems.size();
uint32 uBoxHeight = min( iNumItems, iMaxMenuItems ) * ( MENU_FONT_HEIGHT + MENU_ITEM_PADDING );
uint32 yPos = m_pGameEngine->GetViewportHeight()/2 - uBoxHeight/2;
RECT rect;
rect.top = yPos;
rect.bottom = yPos + MENU_FONT_HEIGHT + MENU_ITEM_PADDING;
rect.left = 0;
rect.right = m_pGameEngine->GetViewportWidth();
char rgchBuffer[256];
if ( m_sHeading.length() )
{
DWORD dwColor = D3DCOLOR_ARGB( 255, 255, 128, 128 );
RECT rect;
rect.top = 10;
rect.bottom = rect.top + MENU_FONT_HEIGHT + ( MENU_ITEM_PADDING * 2 );
rect.left = 0;
rect.right = m_pGameEngine->GetViewportWidth();
m_pGameEngine->BDrawString( g_hMenuFont, rect, dwColor, DT_CENTER|DT_VCENTER, m_sHeading.c_str() );
}
int32 iStartItem = 0;
int32 iEndItem = iNumItems;
if ( iNumItems > iMaxMenuItems )
{
iStartItem = max( (int32)m_uSelectedItem - iMaxMenuItems/2, 0 );
iEndItem = min( iStartItem + iMaxMenuItems, iNumItems );
}
if ( iStartItem > 0 )
{
// Draw ... Scroll Up ...
DWORD dwColor = D3DCOLOR_ARGB( 255, 255, 255, 255 );
m_pGameEngine->BDrawString( g_hMenuFont, rect, dwColor, DT_CENTER|DT_VCENTER, "... Scroll Up ..." );
rect.top = rect.bottom;
rect.bottom += MENU_FONT_HEIGHT + MENU_ITEM_PADDING;
}
for( int32 i=iStartItem; i<iEndItem; ++i )
{
// Empty strings can be used to space menus, they don't get drawn or selected
if ( strlen( m_VecMenuItems[i].first.c_str() ) > 0 )
{
DWORD dwColor;
if ( i == m_uSelectedItem )
{
dwColor = D3DCOLOR_ARGB( 255, 25, 200, 25 );
_snprintf( rgchBuffer, sizeof( rgchBuffer), "{ %s }", m_VecMenuItems[i].first.c_str() );
}
else
{
dwColor = D3DCOLOR_ARGB( 255, 255, 255, 255 );
_snprintf( rgchBuffer, sizeof( rgchBuffer), "%s", m_VecMenuItems[i].first.c_str() );
}
m_pGameEngine->BDrawString( g_hMenuFont, rect, dwColor, DT_CENTER|DT_VCENTER, rgchBuffer );
}
rect.top = rect.bottom;
rect.bottom += MENU_FONT_HEIGHT + MENU_ITEM_PADDING;
}
if ( iNumItems > iEndItem )
{
// Draw ... Scroll Down ...
DWORD dwColor = D3DCOLOR_ARGB( 255, 255, 255, 255 );
m_pGameEngine->BDrawString( g_hMenuFont, rect, dwColor, DT_CENTER|DT_VCENTER, "... Scroll Down ..." );
rect.top = rect.bottom;
rect.bottom += MENU_FONT_HEIGHT + MENU_ITEM_PADDING;
}
}
private:
// Game engine instance
CGameEngine *m_pGameEngine;
// Heading
std::string m_sHeading;
// Vector of menu options
std::vector< MenuItem_t > m_VecMenuItems;
// Currently selected item index
uint32 m_uSelectedItem;
// pushed selection
bool m_bSelectionPushed;
T m_selection;
};
#endif // MAINMENU_H
+1
View File
@@ -0,0 +1 @@
480
File diff suppressed because it is too large Load Diff
+349
View File
@@ -0,0 +1,349 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Main class for the game engine
//
// $NoKeywords: $
//=============================================================================
#ifndef GAMEENGINE_H
#define GAMEENGINE_H
#include <set>
#include <map>
// How big is the vertex buffer for batching lines in total?
// NOTE: This must be a multiple of the batch size below!!! (crashes will occur if it isn't)
#define LINE_BUFFER_TOTAL_SIZE 1000
// How many lines do we put in the buffer in between flushes?
//
// This should be enough smaller than the total size so that draw calls
// can finish using the data before we wrap around and discard it.
#define LINE_BUFFER_BATCH_SIZE 250
// How big is the vertex buffer for batching points in total?
// NOTE: This must be a multiple of the batch size below!!! (crashes will occur if it isn't)
#define POINT_BUFFER_TOTAL_SIZE 1800
// How many points do we put in the buffer in between flushes?
//
// This should be enough smaller than the total size so that draw calls
// can finish using the data before we wrap around and discard it.
#define POINT_BUFFER_BATCH_SIZE 600
// How big is the vertex buffer for batching quads in total?
// NOTE: This must be a multiple of the batch size below!!! (crashes will occur if it isn't)
#define QUAD_BUFFER_TOTAL_SIZE 1000
// How many quads do we put in the buffer in between flushes?
//
// This should be enough smaller than the total size so that draw calls
// can finish using the data before we wrap around and discard it.
#define QUAD_BUFFER_BATCH_SIZE 250
// Vertex struct for line batches
struct LineVertex_t
{
float x, y, z, rhw;
DWORD color;
};
// Vertex struct for point batches
struct PointVertex_t
{
float x, y, z, rhw;
DWORD color;
};
// Vertex struct for textured quads
struct TexturedQuadVertex_t
{
float x, y, z, rhw;
DWORD color;
float u, v; // texture coordinates
};
// WndProc declaration
LRESULT CALLBACK GameWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
// Typedef for font handles
typedef int HGAMEFONT;
// Typedef for vertex buffer handles
typedef int HGAMEVERTBUF;
// Typedef for texture handles
typedef int HGAMETEXTURE;
class CGameEngine
{
public:
// Static methods for tracing mapping of game engine class instances to hwnds
static CGameEngine * FindEngineInstanceForHWND( HWND hWnd );
static void AddInstanceToHWNDMap( CGameEngine* pInstance, HWND hWnd );
static void RemoveInstanceFromHWNDMap( HWND hWnd );
// Constructor
CGameEngine( HINSTANCE hInstance, int nShowCommand, int32 nWindowWidth, int32 nWindowHeight );
// Destructor
~CGameEngine() { Shutdown(); }
// Check if the game engine is initialized ok and ready for use
bool BReadyForUse() { return m_bEngineReadyForUse; }
// Check if the engine is shutting down
bool BShuttingDown() { return m_bShuttingDown; }
// Set the background color
void SetBackgroundColor( short a, short r, short g, short b );
// Start a frame, clear(), beginscene(), etc
bool StartFrame();
// Finish a frame, endscene(), present(), etc.
void EndFrame();
// Shutdown the game engine
void Shutdown();
// Pump messages from the OS
void MessagePump();
// Accessors for game screen size
int32 GetViewportWidth() { return m_nViewportWidth; }
int32 GetViewportHeight() { return m_nViewportHeight; }
// Function for drawing text to the screen, dwFormat is a combination of flags like DT_LEFT, DT_VCENTER etc...
bool BDrawString( HGAMEFONT hFont, RECT rect, DWORD dwColor, DWORD dwFormat, const char *pchText );
// Create a new font returning our internal handle value for it (0 means failure)
HGAMEFONT HCreateFont( int nHeight, int nFontWeight, bool bItalic, char * pchFont );
// Create a new texture returning our internal handle value for it (0 means failure)
HGAMETEXTURE HCreateTexture( byte *pRGBAData, uint32 uWidth, uint32 uHeight );
// Draw a line, the engine itself will manage batching these (although you can explicitly flush if you need to)
bool BDrawLine( float xPos0, float yPos0, DWORD dwColor0, float xPos1, float yPos1, DWORD dwColor1 );
// Flush the line buffer
bool BFlushLineBuffer();
// Draw a point, the engine itself will manage batching these (although you can explicitly flush if you need to)
bool BDrawPoint( float xPos, float yPos, DWORD dwColor );
// Flush the point buffer
bool BFlushPointBuffer();
// Draw a filled quad
bool BDrawFilledQuad( float xPos0, float yPos0, float xPos1, float yPos1, DWORD dwColor );
// Draw a textured rectangle
bool BDrawTexturedQuad( float xPos0, float yPos0, float xPos1, float yPos1,
float u0, float v0, float u1, float v1, DWORD dwColor, HGAMETEXTURE hTexture );
// Flush any still cached quad buffers
bool BFlushQuadBuffer();
// Track the state of keyboard input
void RecordKeyDown( DWORD dwVK );
void RecordKeyUp( DWORD dwVK );
// Get the current state of a key
bool BIsKeyDown( DWORD dwVK );
// Get current tick count for the game engine
uint64 GetGameTickCount() { return m_ulGameTickCount; }
// Get the tick count elapsed since the previous frame
// bugbug - We use this time to compute things like thrust and acceleration in the game,
// so it's important in doesn't jump ahead by large increments... Need a better
// way to handle that.
uint64 GetGameTicksFrameDelta() { return m_ulGameTickCount - m_ulPreviousGameTickCount; }
// Get the game engines hwnd
HWND GetGameHWND() { return m_hWnd; }
// Check if the game engine hwnd currently has focus (and a working d3d device)
bool BGameEngineHasFocus() { return ::GetForegroundWindow() == m_hWnd && !m_bDeviceLost; }
// Set the max FPS for the engine to run at (will sleep in EndFrame() to limit the rate)
void SetMaxFPS( float flMaxFPS ) { m_flMaxFPS = flMaxFPS; }
private:
// Creates the hwnd for the game
bool BCreateGameWindow( int nShowCommand );
// Initializes D3D for the game
bool BInitializeD3D9();
// Resets all the render, texture, and sampler states to our defaults
void ResetRenderStates();
// Create a new vertex buffer returning our internal handle for it (0 means failure)
HGAMEVERTBUF HCreateVertexBuffer( uint32 nSizeInBytes, DWORD dwUsage, DWORD dwFVF );
// Lock an entire vertex buffer with the specified flags
bool BLockEntireVertexBuffer( HGAMEVERTBUF hVertBuf, void **ppVoid, DWORD dwFlags );
// Unlock a vertex buffer
bool BUnlockVertexBuffer( HGAMEVERTBUF hVertBuf );
// Release a vertex buffer and free its resources
bool BReleaseVertexBuffer( HGAMEVERTBUF hVertBuf );
// Set steam source
bool BSetStreamSource( HGAMEVERTBUF hVertBuf, uint32 uOffset, uint32 uStride );
// Render primitives out of the current stream source
bool BRenderPrimitive( D3DPRIMITIVETYPE primType, uint32 uStartVertex, uint32 uCount );
// Set vertex format
bool BSetFVF( DWORD dwFormat );
// Handle losing the d3d device (ie, release resources)
bool BHandleLostDevice();
// Handle reseting the d3d device (ie, acquire resources again)
bool BHandleResetDevice();
private:
// Tracks whether the engine is ready for use
bool m_bEngineReadyForUse;
// Tracks if we are shutting down
bool m_bShuttingDown;
// Color we clear the background of the window to each frame
DWORD m_dwBackgroundColor;
// HInstance for the application running the engine
HINSTANCE m_hInstance;
// HWND for the engine instance
HWND m_hWnd;
// IDirect3D9 interface
IDirect3D9 *m_pD3D9Interface;
// IDirect3DDevice9 interface
IDirect3DDevice9 *m_pD3D9Device;
// Size of the window to display the game in
int32 m_nWindowWidth;
int32 m_nWindowHeight;
// Size of actual d3d viewport (window size minus borders, title, etc)
int32 m_nViewportWidth;
int32 m_nViewportHeight;
// Next font handle value to give out
HGAMEFONT m_nNextFontHandle;
// Map of font handles to font objects
std::map<HGAMEFONT, ID3DXFont *> m_MapFontInstances;
// Next vertex buffer handle value to give out
HGAMEVERTBUF m_nNextVertBufferHandle;
// Map of handles to vertex buffer objects
struct VertBufData_t
{
bool m_bIsLocked;
IDirect3DVertexBuffer9 * m_pBuffer;
};
std::map<HGAMEVERTBUF, VertBufData_t> m_MapVertexBuffers;
HGAMETEXTURE m_nNextTextureHandle;
// Map of handles to texture objects
struct TextureData_t
{
byte *m_pRGBAData; // We keep a copy of the raw data so we can rebuild textures after a device is lost
uint32 m_uWidth;
uint32 m_uHeight;
LPDIRECT3DTEXTURE9 m_pTexture;
};
std::map<HGAMETEXTURE, TextureData_t> m_MapTextures;
// Vertex buffer for textured quads
HGAMEVERTBUF m_hQuadBuffer;
// Last texture used in drawing a batched quad
HGAMETEXTURE m_hLastTexture;
// Pointer to quad vertex data
TexturedQuadVertex_t *m_pQuadVertexes;
// How many quads are awaiting flushing
DWORD m_dwQuadsToFlush;
// Where does the current batch begin
DWORD m_dwQuadBufferBatchPos;
// White texture used when drawing filled quads
HGAMETEXTURE m_hTextureWhite;
// Currently set FVF format
DWORD m_dwCurrentFVF;
// Map of key state
std::set<DWORD> m_SetKeysDown;
// Current game time in milliseconds
uint64 m_ulGameTickCount;
// Game time at the start of the previous frame
uint64 m_ulPreviousGameTickCount;
// Track whether this is the first frame
bool m_bFirstFrame;
// Value to divide from QueryPerformanceCounter results to get milliseconds
uint64 m_ulPerfCounterToMillisecondsDivisor;
// Last value from QueryPerformanceCounter
uint64 m_ulLastQueryPerformanceCounterValue;
// Maximum FPS to run the engine at
float m_flMaxFPS;
// Map of engine instances by HWND, used in wndproc to find engine instance for messages
static std::map<HWND, CGameEngine *> m_MapEngineInstances;
// Internal vertex buffer for batching line drawing
HGAMEVERTBUF m_hLineBuffer;
// Pointer to actual line buffer memory (valid only while locked)
LineVertex_t *m_pLineVertexes;
// Track how many lines are awaiting flushing in our line buffer
DWORD m_dwLinesToFlush;
// Track where the current batch starts in the vert buffer
DWORD m_dwLineBufferBatchPos;
// Internal vertex buffer for batching point drawing
HGAMEVERTBUF m_hPointBuffer;
// Pointer to actual point buffer memory (valid only while locked)
PointVertex_t *m_pPointVertexes;
// Track how many points are awaiting flushing in our line buffer
DWORD m_dwPointsToFlush;
// Track where the current batch starts in the vert buffer
DWORD m_dwPointBufferBatchPos;
// Track if we have lost the d3d device
bool m_bDeviceLost;
// Presentation parameters, saved in case of lost device needing reset
D3DPRESENT_PARAMETERS m_d3dpp;
};
#endif // GAMEENGINE_H
+315
View File
@@ -0,0 +1,315 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for handling finding & creating lobbies, getting their details,
// and seeing other users in the current lobby
//
//=============================================================================
#include "stdafx.h"
#include "Lobby.h"
//-----------------------------------------------------------------------------
// Purpose: Menu that shows a list of other users in a lobby
//-----------------------------------------------------------------------------
class CLobbyMenu : public CBaseMenu<LobbyMenuItem_t>
{
public:
// Constructor
CLobbyMenu( CGameEngine *pGameEngine ) : CBaseMenu<LobbyMenuItem_t>( pGameEngine ) {}
void Rebuild( const CSteamID &steamIDLobby )
{
PushSelectedItem();
ClearMenuItems();
// list of users in lobby
// iterate all the users in the lobby and show their details
int cLobbyMembers = SteamMatchmaking()->GetNumLobbyMembers( steamIDLobby );
for ( int i = 0; i < cLobbyMembers; i++ )
{
CSteamID steamIDLobbyMember = SteamMatchmaking()->GetLobbyMemberByIndex( steamIDLobby, i ) ;
// we get the details of a user from the ISteamFriends interface
const char *pchName = SteamFriends()->GetFriendPersonaName( steamIDLobbyMember );
// we may not know the name of the other users in the lobby immediately; but we'll receive
// a PersonaStateUpdate_t callback when they do, and we'll rebuild the list then
if ( pchName && *pchName )
{
bool bReady = ( 1 == atoi( SteamMatchmaking()->GetLobbyMemberData( steamIDLobby, steamIDLobbyMember, "ready" ) ) );
LobbyMenuItem_t menuItem = { steamIDLobbyMember };
char rgchMenuText[256];
_snprintf( rgchMenuText, sizeof( rgchMenuText ), "%s %s", pchName, bReady ? "(READY)" : "" );
AddMenuItem( MenuItem_t( std::string( rgchMenuText ), menuItem ) );
}
}
// ready/not ready toggle
{
bool bReady = ( 1 == atoi( SteamMatchmaking()->GetLobbyMemberData( steamIDLobby, SteamUser()->GetSteamID(), "ready" ) ) );
LobbyMenuItem_t menuItem = { CSteamID(), false, true };
if ( bReady )
AddMenuItem( CLobbyMenu::MenuItem_t( "Set myself as Not Ready", menuItem ) );
else
AddMenuItem( CLobbyMenu::MenuItem_t( "Set myself as Ready", menuItem ) );
}
// bugbug taylor make it so we can find out who the lobby owner is
bool bLobbyOwner = true;
// start game
if ( bLobbyOwner )
{
LobbyMenuItem_t menuItem = { CSteamID(), true, false };
AddMenuItem( CLobbyMenu::MenuItem_t( "Start game", menuItem ) );
}
// exit lobby
{
LobbyMenuItem_t menuItem = { CSteamID(), false, false, true };
AddMenuItem( CLobbyMenu::MenuItem_t( "Return to main menu", menuItem ) );
}
// reset selection
PopSelectedItem();
}
};
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CLobby::CLobby( CGameEngine *pGameEngine ) :
m_pGameEngine( pGameEngine ),
m_CallbackPersonaStateChange( this, &CLobby::OnPersonaStateChange ),
m_CallbackLobbyDataUpdate( this, &CLobby::OnLobbyDataUpdate ),
m_CallbackChatDataUpdate( this, &CLobby::OnLobbyChatUpdate )
{
m_pMenu = new CLobbyMenu( pGameEngine );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CLobby::~CLobby()
{
}
//-----------------------------------------------------------------------------
// Purpose: Sets the ID of the lobby to display
//-----------------------------------------------------------------------------
void CLobby::SetLobbySteamID( const CSteamID &steamIDLobby )
{
m_steamIDLobby = steamIDLobby;
m_pMenu->Rebuild( m_steamIDLobby );
}
//-----------------------------------------------------------------------------
// Purpose: Draws the lobby
//-----------------------------------------------------------------------------
void CLobby::RunFrame()
{
m_pMenu->RunFrame();
}
//-----------------------------------------------------------------------------
// Purpose: Handles a user in the lobby changing their name or details
//-----------------------------------------------------------------------------
void CLobby::OnPersonaStateChange( PersonaStateChange_t *pCallback )
{
// callbacks are broadcast to all listeners, so we'll get this for every friend who changes state
// so make sure the user is in the lobby before acting
if ( !SteamFriends()->IsUserInSource( pCallback->m_ulSteamID, m_steamIDLobby ) )
return;
// rebuild the menu
m_pMenu->Rebuild( m_steamIDLobby );
}
//-----------------------------------------------------------------------------
// Purpose: Handles lobby data changing
//-----------------------------------------------------------------------------
void CLobby::OnLobbyDataUpdate( LobbyDataUpdate_t *pCallback )
{
// callbacks are broadcast to all listeners, so we'll get this for every lobby we're requesting
if ( m_steamIDLobby != pCallback->m_ulSteamIDLobby )
return;
// set the heading
m_pMenu->SetHeading( SteamMatchmaking()->GetLobbyData( m_steamIDLobby, "name" ) );
// rebuild the menu
m_pMenu->Rebuild( m_steamIDLobby );
}
//-----------------------------------------------------------------------------
// Purpose: Handles users in the lobby joining or leaving
//-----------------------------------------------------------------------------
void CLobby::OnLobbyChatUpdate( LobbyChatUpdate_t *pCallback )
{
// callbacks are broadcast to all listeners, so we'll get this for every lobby we're requesting
if ( m_steamIDLobby != pCallback->m_ulSteamIDLobby )
return;
// rebuild the menu
m_pMenu->Rebuild( m_steamIDLobby );
}
//-----------------------------------------------------------------------------
// Purpose: Menu that shows a list of lobbies to choose from
//-----------------------------------------------------------------------------
class CLobbyBrowserMenu : public CBaseMenu<LobbyBrowserMenuItem_t>
{
public:
// Constructor
CLobbyBrowserMenu( CGameEngine *pGameEngine ) : CBaseMenu<LobbyBrowserMenuItem_t>( pGameEngine ) {}
void Rebuild( std::list<Lobby_t> &listLobbies )
{
PushSelectedItem();
ClearMenuItems();
LobbyBrowserMenuItem_t data;
std::list<Lobby_t>::iterator iter;
for( iter = listLobbies.begin(); iter != listLobbies.end(); ++iter )
{
data.m_eStateToTransitionTo = k_EClientJoiningLobby;
data.m_steamIDLobby = iter->m_steamIDLobby;
if ( iter->m_rgchName[0] )
{
AddMenuItem( MenuItem_t( std::string( iter->m_rgchName ), data ) );
}
}
data.m_eStateToTransitionTo = k_EClientGameMenu;
AddMenuItem( CLobbyBrowserMenu::MenuItem_t( "Return to main menu", data ) );
// reset selection
PopSelectedItem();
}
};
//-----------------------------------------------------------------------------
// Purpose: Constructor
// just initializes base data
//-----------------------------------------------------------------------------
CLobbyBrowser::CLobbyBrowser( CGameEngine *pGameEngine ) :
m_CallbackLobbyMatchList( this, &CLobbyBrowser::OnLobbyMatchListCallback ),
m_CallbackLobbyDataUpdated( this, &CLobbyBrowser::OnLobbyDataUpdatedCallback )
{
m_pGameEngine = pGameEngine;
m_pMenu = new CLobbyBrowserMenu( pGameEngine );
m_pMenu->Rebuild( m_ListLobbies );
m_pMenu->SetHeading( "Lobby browser" );
m_bRequestingLobbies = false;
Refresh();
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CLobbyBrowser::~CLobbyBrowser()
{
delete m_pMenu;
}
//-----------------------------------------------------------------------------
// Purpose: Run a frame (to handle KB input and such as well as render)
//-----------------------------------------------------------------------------
void CLobbyBrowser::RunFrame()
{
m_pMenu->RunFrame();
}
//-----------------------------------------------------------------------------
// Purpose: Starts rebuilding the lobby list
//-----------------------------------------------------------------------------
void CLobbyBrowser::Refresh()
{
if ( !m_bRequestingLobbies )
{
m_bRequestingLobbies = true;
// request all lobbies for this game
SteamMatchmaking()->RequestLobbyList();
}
}
//-----------------------------------------------------------------------------
// Purpose: Callback, on a list of lobbies being received from the Steam back-end
//-----------------------------------------------------------------------------
void CLobbyBrowser::OnLobbyMatchListCallback( LobbyMatchList_t *pCallback )
{
m_ListLobbies.clear();
m_bRequestingLobbies = false;
// lobbies are returned in order of closeness to the user, so add them to the list in that order
for ( uint32 iLobby = 0; iLobby < pCallback->m_nLobbiesMatching; iLobby++ )
{
CSteamID steamIDLobby = SteamMatchmaking()->GetLobbyByIndex( iLobby );
// add the lobby to the list
Lobby_t lobby;
lobby.m_steamIDLobby = steamIDLobby;
// pull the name from the lobby metadata
const char *pchLobbyName = SteamMatchmaking()->GetLobbyData( steamIDLobby, "name" );
if ( pchLobbyName && pchLobbyName[0] )
{
// set the lobby name
_snprintf( lobby.m_rgchName, sizeof( lobby.m_rgchName ), "%s", pchLobbyName );
}
else
{
// we don't have info about the lobby yet, request it
SteamMatchmaking()->RequestLobbyData( steamIDLobby );
// results will be returned via LobbyDataUpdate_t callback
_snprintf( lobby.m_rgchName, sizeof( lobby.m_rgchName ), "Lobby %d", steamIDLobby.GetAccountID() );
}
m_ListLobbies.push_back( lobby );
}
m_pMenu->Rebuild( m_ListLobbies );
}
//-----------------------------------------------------------------------------
// Purpose: Callback, on a list of lobbies being received from the Steam back-end
//-----------------------------------------------------------------------------
void CLobbyBrowser::OnLobbyDataUpdatedCallback( LobbyDataUpdate_t *pCallback )
{
// find the lobby in our local list
std::list<Lobby_t>::iterator iter;
for( iter = m_ListLobbies.begin(); iter != m_ListLobbies.end(); ++iter )
{
// update the name of the lobby
if ( iter->m_steamIDLobby == pCallback->m_ulSteamIDLobby )
{
// extract the display name from the lobby metadata
const char *pchLobbyName = SteamMatchmaking()->GetLobbyData( iter->m_steamIDLobby, "name" );
if ( pchLobbyName[0] )
{
_snprintf( iter->m_rgchName, sizeof( iter->m_rgchName ), "%s", pchLobbyName );
// update the menu
m_pMenu->Rebuild( m_ListLobbies );
}
return;
}
}
}
+94
View File
@@ -0,0 +1,94 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for handling finding & creating lobbies, getting their details,
// and seeing other users in the current lobby
//
//=============================================================================
#ifndef LOBBY_H
#define LOBBY_H
#include "SpaceWar.h"
#include "GameEngine.h"
#include "steam/isteammatchmaking.h"
#include "BaseMenu.h"
#include <list>
class CSpaceWarClient;
class CLobbyBrowserMenu;
class CLobbyMenu;
//-----------------------------------------------------------------------------
// Purpose: Displays the other users in a lobby and allows the game to be started
//-----------------------------------------------------------------------------
class CLobby
{
public:
CLobby( CGameEngine *pGameEngine );
~CLobby();
// sets which lobby to display
void SetLobbySteamID( const CSteamID &steamIDLobby );
// Run a frame (to handle KB input and such as well as render)
void RunFrame();
private:
CSteamID m_steamIDLobby;
// Pointer to engine instance (so we can draw stuff)
CGameEngine *m_pGameEngine;
// Menu object
CLobbyMenu *m_pMenu;
// user state change handler
STEAM_CALLBACK( CLobby, OnPersonaStateChange, PersonaStateChange_t, m_CallbackPersonaStateChange );
// lobby state change handler
STEAM_CALLBACK( CLobby, OnLobbyDataUpdate, LobbyDataUpdate_t, m_CallbackLobbyDataUpdate );
STEAM_CALLBACK( CLobby, OnLobbyChatUpdate, LobbyChatUpdate_t, m_CallbackChatDataUpdate );
};
// an item in the list of lobbies we've found to display
struct Lobby_t
{
CSteamID m_steamIDLobby;
char m_rgchName[256];
};
//-----------------------------------------------------------------------------
// Purpose: Displaying and allows selection from a list of lobbies
//-----------------------------------------------------------------------------
class CLobbyBrowser
{
public:
CLobbyBrowser( CGameEngine *pGameEngine );
~CLobbyBrowser();
// rebuild the list
void Refresh();
// Run a frame (to handle KB input and such as well as render)
void RunFrame();
private:
// Pointer to engine instance (so we can draw stuff)
CGameEngine *m_pGameEngine;
// Track whether we are in the middle of a refresh or not
bool m_bRequestingLobbies;
// Menu object
CLobbyBrowserMenu *m_pMenu;
STEAM_CALLBACK( CLobbyBrowser, OnLobbyMatchListCallback, LobbyMatchList_t, m_CallbackLobbyMatchList );
STEAM_CALLBACK( CLobbyBrowser, OnLobbyDataUpdatedCallback, LobbyDataUpdate_t, m_CallbackLobbyDataUpdated );
std::list< Lobby_t > m_ListLobbies;
};
#endif //LOBBY_H
+176
View File
@@ -0,0 +1,176 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose: Main file for the SteamworksExample app
//
//=============================================================================
#include "stdafx.h"
#include "GameEngine.h"
#include "SpaceWarClient.h"
#include "steam/steam_api.h"
//-----------------------------------------------------------------------------
// Purpose: Wrapper around SteamAPI_WriteMiniDump which can be used directly
// as a se translator
//-----------------------------------------------------------------------------
void MiniDumpFunction( unsigned int nExceptionCode, EXCEPTION_POINTERS *pException )
{
// You can build and set an arbitrary comment to embed in the minidump here,
// maybe you want to put what level the user was playing, how many players on the server,
// how much memory is free, etc...
SteamAPI_SetMiniDumpComment( "Minidump comment: SteamworksExample.exe\n" );
// The 0 here is a build ID, we don't set it
SteamAPI_WriteMiniDump( nExceptionCode, pException, 0 );
}
//-----------------------------------------------------------------------------
// Purpose: callback hook for debug text emitted from the Steam API
//-----------------------------------------------------------------------------
extern "C" void __cdecl SteamAPIDebugTextHook( int nSeverity, const char *pchDebugText )
{
// if you're running in the debugger, only warnings (nSeverity >= 1) will be sent
// if you add -debug_steamapi to the command-line, a lot of extra informational messages will also be sent
::OutputDebugString( pchDebugText );
if ( nSeverity >= 1 )
{
// place to set a breakpoint for catching API errors
int x = 3;
x;
}
}
//-----------------------------------------------------------------------------
// Purpose: Real main entry point for the program
//-----------------------------------------------------------------------------
int APIENTRY RealMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// Initialize SteamAPI, if this fails we bail out since we depend on Steam for lots of stuff.
// You don't necessarily have to though if you write your code to check whether all the Steam
// interfaces are NULL before using them and provide alternate paths when they are unavailable.
//
// This will also load the in-game steam overlay dll into your process. That dll is normally
// injected by steam when it launches games, but by calling this you cause it to always load,
// even when not launched via steam.
if ( !SteamAPI_Init() )
{
OutputDebugString( "SteamAPI_Init() failed\n" );
::MessageBox( NULL, "Steam must be running to play this game (SteamAPI_Init() failed).\n", "Fatal Error", MB_OK );
return -1;
}
// set our debug handler
SteamClient()->SetWarningMessageHook( &SteamAPIDebugTextHook );
// Look for the +connect ipaddress:port parameter in the command line,
// Steam will pass this when a user has used the Steam Server browser to find
// a server for our game and is trying to join it.
const char* pchConnectParam = "+connect";
char *pchCmdLine = ::GetCommandLine();
char *pchConnect = strstr( pchCmdLine, pchConnectParam );
char *pchServerAddress = NULL;
if ( pchConnect && strlen( pchCmdLine ) > (pchConnect - pchCmdLine) + strlen( pchConnectParam ) + 1 )
{
// Address should be right after the +connect, +1 on the end to skip the space
pchServerAddress = pchCmdLine + ( pchConnect - pchCmdLine ) + strlen( pchConnectParam ) + 1;
}
// Construct a new instance of the game engine
// bugbug jmccaskey - make screen resolution dynamic, maybe take it on command line?
CGameEngine *pGameEngine = new CGameEngine( hInstance, nCmdShow, 1024, 768 );
// Make sure it initialized ok
if ( pGameEngine->BReadyForUse() )
{
// Initialize the game
CSpaceWarClient *pGameClient = new CSpaceWarClient( pGameEngine, SteamUser()->GetSteamID() );
// Black background
pGameEngine->SetBackgroundColor( 0, 0, 0, 0 );
// Set max FPS
pGameEngine->SetMaxFPS( MAX_CLIENT_AND_SERVER_FPS );
// If +connect was used to specify a server address, connect now
if ( pchServerAddress )
{
int32 octet0 = 0, octet1 = 0, octet2 = 0, octet3 = 0;
int32 uPort = 0;
int nConverted = sscanf( pchServerAddress, "%d.%d.%d.%d:%d", &octet0, &octet1, &octet2, &octet3, &uPort );
if ( nConverted == 5 )
{
char rgchIPAddress[128];
_snprintf( rgchIPAddress, ARRAYSIZE( rgchIPAddress ), "%d.%d.%d.%d", octet0, octet1, octet2, octet3 );
uint32 unIPAddress = ( octet3 ) + ( octet2 << 8 ) + ( octet1 << 16 ) + ( octet0 << 24 );
pGameClient->InitiateServerConnection( unIPAddress, uPort );
}
}
while( !pGameEngine->BShuttingDown() )
{
if ( pGameEngine->StartFrame() )
{
// Run a game frame
pGameClient->RunFrame();
pGameEngine->EndFrame();
}
}
delete pGameClient;
}
// Cleanup the game engine
delete pGameEngine;
// Shutdown the SteamAPI
SteamAPI_Shutdown();
// exit
return 0;
}
//-----------------------------------------------------------------------------
// Purpose: Main entry point for the program
//-----------------------------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// All we do here is call the real main function after setting up our se translator
// this allows us to catch exceptions and report errors to Steam.
//
// Note that you must set your compiler flags correctly to enable structured exception
// handling in order for this particular setup method to work.
if ( IsDebuggerPresent() )
{
// We don't want to mask exceptions (or report them to Steam!) when debugging
return RealMain( hInstance, hPrevInstance, lpCmdLine, nCmdShow );
}
_set_se_translator( MiniDumpFunction );
try // this try block allows the SE translator to work
{
return RealMain( hInstance, hPrevInstance, lpCmdLine, nCmdShow );
}
catch( ... )
{
return -1;
}
}
+26
View File
@@ -0,0 +1,26 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class to define the main game menu
//
// $NoKeywords: $
//=============================================================================
#include "stdafx.h"
#include "MainMenu.h"
#include "SpaceWar.h"
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CMainMenu::CMainMenu( CGameEngine *pGameEngine ) : CBaseMenu<EClientGameState>( pGameEngine )
{
AddMenuItem( MenuItem_t( "Start New Server", k_EClientGameStartServer ) );
AddMenuItem( MenuItem_t( "Find LAN Servers", k_EClientFindLANServers ) );
AddMenuItem( MenuItem_t( "Find Internet Servers", k_EClientFindInternetServers ) );
AddMenuItem( MenuItem_t( "Create Lobby", k_EClientCreatingLobby ) );
AddMenuItem( MenuItem_t( "Find Lobby", k_EClientFindLobby ) );
AddMenuItem( MenuItem_t( "Instructions", k_EClientGameInstructions ) );
AddMenuItem( MenuItem_t( "Stats and Achievements", k_EClientStatsAchievements ) );
AddMenuItem( MenuItem_t( "Exit Game", k_EClientGameExiting ) );
}
+25
View File
@@ -0,0 +1,25 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class to define the main game menu
//
// $NoKeywords: $
//=============================================================================
#ifndef MAINMENU_H
#define MAINMENU_H
#include <string>
#include <vector>
#include "GameEngine.h"
#include "SpaceWar.h"
#include "BaseMenu.h"
#include "SpaceWarClient.h"
class CMainMenu : public CBaseMenu<EClientGameState>
{
public:
// Constructor
CMainMenu( CGameEngine *pGameEngine );
};
#endif // MAINMENU_H
+119
View File
@@ -0,0 +1,119 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Defines the wire protocol for the game
//
// $NoKeywords: $
//=============================================================================
#ifndef MESSAGES_H
#define MESSAGES_H
#include <map>
// Network message types
enum EMessage
{
// Server messages
k_EMsgServerBegin = 0,
k_EMsgServerSendInfo = k_EMsgServerBegin+1,
k_EMsgServerFailAuthentication = k_EMsgServerBegin+2,
k_EMsgServerPassAuthentication = k_EMsgServerBegin+3,
k_EMsgServerUpdateWorld = k_EMsgServerBegin+4,
k_EMsgServerExiting = k_EMsgServerBegin+5,
// Client messages
k_EMsgClientBegin = 500,
k_EMsgClientInitiateConnection = k_EMsgClientBegin+1,
k_EMsgClientBeginAuthentication = k_EMsgClientBegin+2,
k_EMsgClientSendLocalUpdate = k_EMsgClientBegin+3,
k_EMsgClientLeavingServer = k_EMsgClientBegin+4,
// force 32-bit size enum so the wire protocol doesn't get outgrown later
k_EForceDWORD = 0x7fffffff,
};
// Msg from the server to the client which is sent right after communications are established
// and tells the client what SteamID the game server is using as well as whether the server is secure
struct MsgServerSendInfo_t
{
MsgServerSendInfo_t() : m_dwMessageType( k_EMsgServerSendInfo ) {}
const DWORD m_dwMessageType;
uint64 m_ulSteamIDServer;
bool m_bIsVACSecure;
char m_rgchServerName[128];
};
// Msg from the server to the client when refusing a connection
struct MsgServerFailAuthentication_t
{
MsgServerFailAuthentication_t() : m_dwMessageType( k_EMsgServerFailAuthentication ) {}
const DWORD m_dwMessageType;
};
// Msg from the server to client when accepting a pending connection
struct MsgServerPassAuthentication_t
{
MsgServerPassAuthentication_t() : m_dwMessageType( k_EMsgServerPassAuthentication ) {}
const DWORD m_dwMessageType;
uint32 m_uPlayerPosition;
};
// Msg from the server to clients when updating the world state
struct MsgServerUpdateWorld_t
{
MsgServerUpdateWorld_t() : m_dwMessageType( k_EMsgServerUpdateWorld ) {}
const DWORD m_dwMessageType;
ServerSpaceWarUpdateData_t m_ServerUpdateData;
};
// Msg from server to clients when it is exiting
struct MsgServerExiting_t
{
MsgServerExiting_t() : m_dwMessageType( k_EMsgServerExiting ) {}
const DWORD m_dwMessageType;
};
// Msg from client to server when trying to connect
struct MsgClientInitiateConnection_t
{
MsgClientInitiateConnection_t() : m_dwMessageType( k_EMsgClientInitiateConnection ) {}
const DWORD m_dwMessageType;
};
// Msg from client to server when initiating authentication
struct MsgClientBeginAuthentication_t
{
MsgClientBeginAuthentication_t() : m_dwMessageType( k_EMsgClientBeginAuthentication ) {}
const DWORD m_dwMessageType;
uint64 m_ulSteamID;
uint32 m_uTokenLen;
char m_rgchToken[1024];
};
// Msg from client to server when sending state update
struct MsgClientSendLocalUpdate_t
{
MsgClientSendLocalUpdate_t() : m_dwMessageType( k_EMsgClientSendLocalUpdate ) {}
const DWORD m_dwMessageType;
uint32 m_uShipPosition;
ClientSpaceWarUpdateData_t m_ClientUpdateData;
};
// Msg from the client telling the server it is about to leave
struct MsgClientLeavingServer_t
{
MsgClientLeavingServer_t() : m_dwMessageType( k_EMsgClientLeavingServer ) {}
const DWORD m_dwMessageType;
};
#endif // MESSAGES_H
+40
View File
@@ -0,0 +1,40 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for rendering photon beams
//
// $NoKeywords: $
//=============================================================================
#include "stdafx.h"
#include "PhotonBeam.h"
#include "SpaceWar.h"
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CPhotonBeam::CPhotonBeam( CGameEngine *pGameEngine, float xPos, float yPos, DWORD dwBeamColor, float flInitialRotation, float flInitialXVelocity, float flInitialYVelocity )
: CSpaceWarEntity( pGameEngine, 3, true )
{
// Beams only have a lifetime of 1 second
m_ulTickCountToDieAt = m_pGameEngine->GetGameTickCount()+PHOTON_BEAM_LIFETIME_IN_TICKS;
// Set a really high max velocity for photon beams
SetMaximumVelocity( 500 );
AddLine( -2.0f, -3.0f, -2.0f, 3.0f, dwBeamColor );
AddLine( 2.0f, -3.0f, 2.0f, 3.0f, dwBeamColor );
SetPosition( xPos, yPos );
SetRotationDeltaNextFrame( flInitialRotation );
SetVelocity( flInitialXVelocity, flInitialYVelocity );
}
//-----------------------------------------------------------------------------
// Purpose: Update with data from server
//-----------------------------------------------------------------------------
void CPhotonBeam::OnReceiveServerUpdate( ServerPhotonBeamUpdateData_t UpdateData )
{
SetPosition( UpdateData.m_flXPosition, UpdateData.m_flYPosition );
SetVelocity( UpdateData.m_flXVelocity, UpdateData.m_flYVelocity );
SetAccumulatedRotation( UpdateData.m_flCurrentRotation );
}
+31
View File
@@ -0,0 +1,31 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for rendering photon beams
//
// $NoKeywords: $
//=============================================================================
#ifndef PHOTONBEAM_H
#define PHOTONBEAM_H
#include "GameEngine.h"
#include "SpaceWarEntity.h"
#include "SpaceWar.h"
class CPhotonBeam : public CSpaceWarEntity
{
public:
// Constructor
CPhotonBeam( CGameEngine *pGameEngine, float xPos, float yPos, DWORD dwBeamColor, float flInitialRotation, float flInitialXVelocity, float flInitialYVelocity );
// Check if the photon beam needs to die
bool BIsBeamExpired() { return m_pGameEngine->GetGameTickCount() > m_ulTickCountToDieAt; }
// Update with new data from server
void OnReceiveServerUpdate( ServerPhotonBeamUpdateData_t UpdateData );
private:
uint64 m_ulTickCountToDieAt;
};
#endif // PHOTONBEAM_H
+21
View File
@@ -0,0 +1,21 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class to define the pause menu
//
// $NoKeywords: $
//=============================================================================
#include "stdafx.h"
#include "QuitMenu.h"
#include "SpaceWar.h"
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CQuitMenu::CQuitMenu( CGameEngine *pGameEngine ) : CBaseMenu<EClientGameState>( pGameEngine )
{
AddMenuItem( MenuItem_t( "Resume Game", k_EClientGameActive ) );
AddMenuItem( MenuItem_t( "Exit To Menu", k_EClientGameMenu ) );
AddMenuItem( MenuItem_t( "Exit To Desktop", k_EClientGameExiting ) );
}
+25
View File
@@ -0,0 +1,25 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class to define the pause game menu
//
// $NoKeywords: $
//=============================================================================
#ifndef QUITMENU_H
#define QUITMENU_H
#include <string>
#include <vector>
#include "GameEngine.h"
#include "SpaceWar.h"
#include "BaseMenu.h"
#include "SpaceWarClient.h"
class CQuitMenu : public CBaseMenu<EClientGameState>
{
public:
// Constructor
CQuitMenu( CGameEngine *pGameEngine );
};
#endif // QUITMENU_H
@@ -0,0 +1 @@
480
+176
View File
@@ -0,0 +1,176 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for handling finding servers, getting their details, and displaying
// them inside the game
//
// $NoKeywords: $
//=============================================================================
#include "stdafx.h"
#include "ServerBrowser.h"
#include "ServerBrowserMenu.h"
//-----------------------------------------------------------------------------
// Purpose: Constructor -- initialize from steam gameserveritem_t
//-----------------------------------------------------------------------------
CGameServer::CGameServer( gameserveritem_t *pGameServerItem )
{
m_unIPAddress = pGameServerItem->m_NetAdr.GetIP();
m_nConnectionPort = pGameServerItem->m_NetAdr.GetConnectionPort();
m_nPing = pGameServerItem->m_nPing;
strncpy( m_szMap, pGameServerItem->m_szMap, ARRAYSIZE( m_szMap ) );
strncpy( m_szGameDescription, pGameServerItem->m_szGameDescription, ARRAYSIZE( m_szGameDescription ) );
m_nPlayers = pGameServerItem->m_nPlayers;
m_nMaxPlayers = pGameServerItem->m_nMaxPlayers;
m_nBotPlayers = pGameServerItem->m_nBotPlayers;
m_bPassword = pGameServerItem->m_bPassword;
m_bSecure = pGameServerItem->m_bSecure;
m_nServerVersion = pGameServerItem->m_nServerVersion;
strncpy( m_szServerName, pGameServerItem->GetName(), ARRAYSIZE( m_szServerName ) );
_snprintf( m_szServerString, ARRAYSIZE( m_szServerString ), "%s (%i/%i) at %s ping(%d)", pGameServerItem->GetName(), pGameServerItem->m_nPlayers, pGameServerItem->m_nMaxPlayers, pGameServerItem->m_NetAdr.GetConnectionAddressString(), pGameServerItem->m_nPing );
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CServerBrowser::CServerBrowser( CGameEngine *pGameEngine )
{
m_pMenu = new CServerBrowserMenu( pGameEngine );
m_pGameEngine = pGameEngine;
m_nServers = 0;
m_bRequestingServers = false;
m_ServerType = eInternetServer;
m_pMenu->Rebuild( m_ListGameServers, m_bRequestingServers );
m_pMenu->SetHeading( "Internet Server browser" );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CServerBrowser::~CServerBrowser()
{
if ( m_pMenu )
delete m_pMenu;
// ...
}
//-----------------------------------------------------------------------------
// Purpose: Initiate a refresh of internet servers
//-----------------------------------------------------------------------------
void CServerBrowser::RefreshInternetServers()
{
// If we are still finishing the previous refresh, then ignore this new request
if ( m_bRequestingServers )
return;
OutputDebugString( "Refreshing internet servers\n" );
// Track that we are now in a refresh, what type of refresh, and reset our server count
m_bRequestingServers = true;
m_ServerType = eInternetServer;
m_nServers = 0;
m_ListGameServers.clear();
m_pMenu->SetHeading( "Internet Server browser" );
m_pMenu->Rebuild( m_ListGameServers, m_bRequestingServers );
// Allocate some filters, there are some common pre-defined values that can be used:
//
// "gamedir" -- this is used to specify mods inside or a single product/appid
// "secure" -- this is used to specify whether anti-cheat is enabled for a server
// "gametype" -- this is used to specify game type and is set to whatever your game server code sets
MatchMakingKeyValuePair_t pFilters[2];
MatchMakingKeyValuePair_t *pFilter = pFilters;
strncpy( pFilters[ 0 ].m_szKey, "gamedir", sizeof(pFilters[ 0 ].m_szKey) );
strncpy( pFilters[ 0 ].m_szValue, "spacewar", sizeof(pFilters[ 0 ].m_szValue) );
strncpy( pFilters[ 1 ].m_szKey, "secure", sizeof(pFilters[ 1 ].m_szKey) );
strncpy( pFilters[ 1 ].m_szValue, "1", sizeof(pFilters[ 1 ].m_szValue) );
//strncpy( pFilters[ 2 ].m_szKey, "gametype", sizeof(pFilters[ 1 ].m_szValue) );
//strncpy( pFilters[ 2 ].m_szValue, "dm", sizeof(pFilters[ 1 ].m_szValue) );
// bugbug jmccaskey - passing just the appid without filters results in getting all servers rather than
// servers filtered by appid alone. So, we'll use the filters to filter the results better.
SteamMatchmakingServers()->RequestInternetServerList( SteamUtils()->GetAppID(), &pFilter, ARRAYSIZE(pFilters), this );
}
//-----------------------------------------------------------------------------
// Purpose: Initiate a refresh of LAN servers
//-----------------------------------------------------------------------------
void CServerBrowser::RefreshLANServers()
{
// If we are still finishing the previous refresh, then ignore this new request
if ( m_bRequestingServers )
return;
OutputDebugString( "Refreshing internet servers\n" );
// Track that we are now in a refresh, what type of refresh, and reset our server count
m_bRequestingServers = true;
m_ServerType = eLANServer;
m_nServers = 0;
m_ListGameServers.clear();
m_pMenu->SetHeading( "LAN Server browser" );
m_pMenu->Rebuild( m_ListGameServers, m_bRequestingServers );
// LAN refresh doesn't accept filters like internet above does
SteamMatchmakingServers()->RequestLANServerList( SteamUtils()->GetAppID(), this );
}
//-----------------------------------------------------------------------------
// Purpose: Callback from Steam telling us about a server that has responded
//-----------------------------------------------------------------------------
void CServerBrowser::ServerResponded( int iServer )
{
gameserveritem_t *pServer = SteamMatchmakingServers()->GetServerDetails( m_ServerType, iServer );
if ( pServer )
{
// Filter out servers that don't match our appid here (might get these in LAN calls since we can't put more filters on it)
if ( pServer->m_nAppID == SteamUtils()->GetAppID() )
{
m_ListGameServers.push_back( CGameServer( pServer ) );
m_nServers++;
}
}
// Rebuild menu
m_pMenu->Rebuild( m_ListGameServers, m_bRequestingServers );
}
//-----------------------------------------------------------------------------
// Purpose: Callback from Steam telling us about a server that has failed to respond
//-----------------------------------------------------------------------------
void CServerBrowser::ServerFailedToRespond( int iServer )
{
// bugbug jmccaskey - why would we ever need this? Remove servers from our list I guess?
}
//-----------------------------------------------------------------------------
// Purpose: Callback from Steam telling us a refresh is complete
//-----------------------------------------------------------------------------
void CServerBrowser::RefreshComplete( EMatchMakingServerResponse response )
{
// Doesn't really matter to us whether the response tells us the refresh succeeded or failed,
// we just rack whether we are done refreshing or not
m_bRequestingServers = false;
}
//-----------------------------------------------------------------------------
// Purpose: Run a server browser frame (does stuff like checking KB input to change state)
//-----------------------------------------------------------------------------
void CServerBrowser::RunFrame()
{
m_pMenu->RunFrame();
}
+93
View File
@@ -0,0 +1,93 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for handling finding servers, getting their details, and displaying
// them inside the game
//
// $NoKeywords: $
//=============================================================================
#ifndef SERVERBROWSER_H
#define SERVERBROWSER_H
#include "SpaceWar.h"
#include "GameEngine.h"
#include "steam/isteammatchmaking.h"
#include "BaseMenu.h"
#include <list>
class CSpaceWarClient;
class CServerBrowserMenu;
// Class to encapsulate game server data
class CGameServer
{
public:
CGameServer( gameserveritem_t *pGameServerItem );
const char* GetName() { return m_szServerName; }
const char* GetDisplayString() { return m_szServerString; }
uint32 GetIP() { return m_unIPAddress; }
int32 GetPort() { return m_nConnectionPort; }
private:
uint32 m_unIPAddress; // IP address for the server
int32 m_nConnectionPort; // Port for game clients to connect to for this server
int m_nPing; // current ping time in milliseconds
char m_szMap[32]; // current map
char m_szGameDescription[64]; // game description
int m_nPlayers; // current number of players on the server
int m_nMaxPlayers; // Maximum players that can join this server
int m_nBotPlayers; // Number of bots (i.e simulated players) on this server
bool m_bPassword; // true if this server needs a password to join
bool m_bSecure; // Is this server protected by VAC
int m_nServerVersion; // server version as reported to Steam
char m_szServerName[64]; // Game server name
char m_szServerString[128]; // String to show in server browser
};
class CServerBrowser : public ISteamMatchmakingServerListResponse
{
public:
CServerBrowser( CGameEngine *pGameEngine );
~CServerBrowser();
// Initiate a refresh of internet servers
void RefreshInternetServers();
// Initiate a refresh of LAN servers
void RefreshLANServers();
// Run a frame (to handle kb input and such as well as render)
void RunFrame();
// ISteamMatchmakingServerListResponse
void ServerResponded( int iServer );
void ServerFailedToRespond( int iServer );
void RefreshComplete( EMatchMakingServerResponse response );
private:
// Pointer to engine instance (so we can draw stuff)
CGameEngine *m_pGameEngine;
// Track the number of servers we know about
int m_nServers;
// Track whether we are in the middle of a refresh or not
bool m_bRequestingServers;
// Track what type of servers we are currently displaying
EMatchMakingType m_ServerType;
// Menu object
CServerBrowserMenu *m_pMenu;
// List of game servers
std::list< CGameServer > m_ListGameServers;
};
#endif //SERVERBROWSER_H
+41
View File
@@ -0,0 +1,41 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class to find servers menu
//
//=============================================================================
#ifndef SERVERBROWSERMENU_H
#define SERVERBROWSERMENU_H
#include "BaseMenu.h"
#include "ServerBrowser.h"
class CServerBrowserMenu : public CBaseMenu<ServerBrowserMenuData_t>
{
public:
// Constructor
CServerBrowserMenu( CGameEngine *pGameEngine ) : CBaseMenu<ServerBrowserMenuData_t>( pGameEngine ) {}
void Rebuild( std::list<CGameServer> &List, bool bIsRefreshing )
{
ClearMenuItems();
ServerBrowserMenuData_t data;
std::list<CGameServer>::iterator iter;
for( iter = List.begin(); iter != List.end(); ++iter )
{
data.m_eStateToTransitionTo = k_EClientGameConnecting;
data.m_unIPAddress = iter->GetIP();
data.m_nConnectionPort = iter->GetPort();
AddMenuItem( MenuItem_t( iter->GetDisplayString(), data ) );
}
data.m_eStateToTransitionTo = k_EClientGameMenu;
AddMenuItem( CServerBrowserMenu::MenuItem_t( "Return to main menu", data ) );
}
};
#endif SERVERBROWSERMENU_H
+623
View File
@@ -0,0 +1,623 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for rendering the player ships
//
// $NoKeywords: $
//=============================================================================
#include "stdafx.h"
#include "Ship.h"
#include "stdlib.h"
#include "SpaceWarServer.h"
#include "StatsAndAchievements.h"
//-----------------------------------------------------------------------------
// Purpose: Constructor for thrusters
//-----------------------------------------------------------------------------
CForwardThrusters::CForwardThrusters( CGameEngine *pGameEngine, CShip *pShip ) : CVectorEntity( pGameEngine, 0 )
{
DWORD dwColor = D3DCOLOR_ARGB( 255, 255, 255, 102 );
// Initialize our geometry
AddLine( 0.0, 12.0f, 0.0f, 19.0f, dwColor );
AddLine( 1.0, 12.0f, 6.0f, 19.0f, dwColor );
AddLine( 4.0, 12.0f, 11.0f, 19.0f, dwColor );
AddLine( -1.0, 12.0f, -6.0f, 19.0f, dwColor );
AddLine( -4.0, 12.0f, -11.0f, 19.0f, dwColor );
m_pShip = pShip;
}
//-----------------------------------------------------------------------------
// Purpose: Run Frame, updates us to be in the same position/rotation as the ship we belong to
//-----------------------------------------------------------------------------
void CForwardThrusters::RunFrame()
{
SetAccumulatedRotation( m_pShip->GetAccumulatedRotation() );
SetPosition( m_pShip->GetXPos(), m_pShip->GetYPos() );
CVectorEntity::RunFrame();
}
//-----------------------------------------------------------------------------
// Purpose: Constructor for reverse thrusters
//-----------------------------------------------------------------------------
CReverseThrusters::CReverseThrusters( CGameEngine *pGameEngine, CShip *pShip ) : CVectorEntity( pGameEngine, 0 )
{
DWORD dwColor = D3DCOLOR_ARGB( 255, 255, 255, 102 );
// Initialize our geometry
AddLine( -8.875, 10.5f, -14.85f, 10.5f, dwColor );
AddLine( -8.875, 10.5f, -13.765f, 5.61f, dwColor );
AddLine( -8.875, 10.5f, -7.85f, 3.5f, dwColor );
AddLine( 8.875, 10.5f, 14.85f, 10.5f, dwColor );
AddLine( 8.875, 10.5f, 13.765f, 5.61f, dwColor );
AddLine( 8.875, 10.5f, 7.85f, 3.5f, dwColor );
m_pShip = pShip;
}
//-----------------------------------------------------------------------------
// Purpose: Run Frame, updates us to be in the same position/rotation as the ship we belong to
//-----------------------------------------------------------------------------
void CReverseThrusters::RunFrame()
{
SetAccumulatedRotation( m_pShip->GetAccumulatedRotation() );
SetPosition( m_pShip->GetXPos(), m_pShip->GetYPos() );
CVectorEntity::RunFrame();
}
//-----------------------------------------------------------------------------
// Purpose: Constructor for ship debris after explosion
//-----------------------------------------------------------------------------
CShipDebris::CShipDebris( CGameEngine *pGameEngine, float xPos, float yPos, DWORD dwDebrisColor ) : CSpaceWarEntity( pGameEngine, 0, true )
{
AddLine( 0.0f, 0.0f, 16.0f, 0.0f, dwDebrisColor );
// Random rotation between 0 and 360 degrees (6.28 radians)
float flRotation = (float)(rand()%628)/100.0f;
SetRotationDeltaNextFrame( flRotation );
// Rotation to apply per second
int nRandRotation = rand()%(157*2) - (157);
m_flRotationPerInterval = nRandRotation/100.0f;
float sinvalue = (float)sin( flRotation );
float cosvalue = (float)cos( flRotation );
float xVelocity = GetXVelocity() + ( sinvalue * 80 );
float yVelocity = GetYVelocity() - ( cosvalue * 80 );
// Offset out a bit from the center of the ship compensating for rotation
float offset = (rand()%12)-6.0f;
float xOffset = xPos + (cosvalue*-offset - sinvalue*-offset);
float yOffset = yPos + (cosvalue*-offset + sinvalue*-offset);
// Set velocity
SetVelocity( xVelocity, yVelocity );
// Set position
SetPosition( xOffset, yOffset );
}
//-----------------------------------------------------------------------------
// Purpose: Run frame for debris (keep it spinning)
//-----------------------------------------------------------------------------
void CShipDebris::RunFrame()
{
SetRotationDeltaNextFrame( m_flRotationPerInterval * min( m_pGameEngine->GetGameTicksFrameDelta(), 400.0f )/400.0f );
CSpaceWarEntity::RunFrame();
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
#pragma warning( push )
// warning C4355: 'this' : used in base member initializer list
// This is OK because the thruster classes won't use the ship object in their constructors (where it may still be only partly constructed)
#pragma warning( disable : 4355 )
CShip::CShip( CGameEngine *pGameEngine, bool bIsServerInstance, float xPos, float yPos, DWORD dwShipColor ) :
CSpaceWarEntity( pGameEngine, 11, true ), m_ForwardThrusters( pGameEngine, this ), m_ReverseThrusters( pGameEngine, this )
{
m_bDisabled = false;
m_bExploding = false;
m_ulLastThrustStartedTickCount = 0;
m_dwVKLeft = 0;
m_dwVKRight = 0;
m_dwVKForwardThrusters = 0;
m_dwVKReverseThrusters = 0;
m_dwVKFire = 0;
m_ulLastPhotonTickCount = 0;
m_dwShipColor = dwShipColor;
m_bForwardThrustersActive = false;
m_bReverseThrustersActive = false;
m_bIsLocalPlayer = false;
m_bFirePhotonBeamNextFrame = false;
m_ulLastClientUpdateTick = 0;
m_bIsServerInstance = bIsServerInstance;
memset( &m_SpaceWarClientUpdateData, 0, sizeof( m_SpaceWarClientUpdateData ) );
for( int i=0; i < MAX_PHOTON_BEAMS_PER_SHIP; ++i )
{
m_rgPhotonBeams[i] = NULL;
}
// Initialize our geometry
AddLine( -9.0f, 12.0f, 0.0f, -12.0f, dwShipColor );
AddLine( 0.0f, -12.0f, 9.0f, 12.0f, dwShipColor );
AddLine( 9.0f, 12.0f, -9.0f, 12.0f, dwShipColor );
SetPosition( xPos, yPos );
}
#pragma warning( pop )
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CShip::~CShip()
{
// Cleanup beams
{
for( int i=0; i < MAX_PHOTON_BEAMS_PER_SHIP; ++i )
{
if ( m_rgPhotonBeams[i] )
delete m_rgPhotonBeams[i];
}
}
// Cleanup debris
{
std::list<CShipDebris *>::iterator iter;
for ( iter = m_ListDebris.begin(); iter != m_ListDebris.end(); ++iter )
{
delete (*iter);
}
m_ListDebris.clear();
}
}
//-----------------------------------------------------------------------------
// Purpose: Update entity with updated data from the server
//-----------------------------------------------------------------------------
void CShip::OnReceiveServerUpdate( ServerShipUpdateData_t UpdateData )
{
if ( m_bIsServerInstance )
{
OutputDebugString( "Should not be receiving server updates on the server itself\n" );
return;
}
SetDisabled( UpdateData.m_bDisabled );
SetExploding( UpdateData.m_bExploding );
SetPosition( UpdateData.m_flXPosition, UpdateData.m_flYPosition );
SetVelocity( UpdateData.m_flXVelocity, UpdateData.m_flYVelocity );
SetAccumulatedRotation( UpdateData.m_flCurrentRotation );
m_bForwardThrustersActive = UpdateData.m_bForwardThrustersActive;
m_bReverseThrustersActive = UpdateData.m_bReverseThrustersActive;
// Update the photon beams
for ( int i=0; i < MAX_PHOTON_BEAMS_PER_SHIP; ++i )
{
if ( UpdateData.m_PhotonBeamData[i].m_bIsActive )
{
if ( !m_rgPhotonBeams[i] )
{
m_rgPhotonBeams[i] = new CPhotonBeam( m_pGameEngine,
UpdateData.m_PhotonBeamData[i].m_flXPosition, UpdateData.m_PhotonBeamData[i].m_flYPosition,
m_dwShipColor, UpdateData.m_PhotonBeamData[i].m_flCurrentRotation,
UpdateData.m_PhotonBeamData[i].m_flXVelocity, UpdateData.m_PhotonBeamData[i].m_flYVelocity );
}
else
{
m_rgPhotonBeams[i]->OnReceiveServerUpdate( UpdateData.m_PhotonBeamData[i] );
}
}
else
{
if ( m_rgPhotonBeams[i] )
{
delete m_rgPhotonBeams[i];
m_rgPhotonBeams[i] = NULL;
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Update entity with updated data from the client
//-----------------------------------------------------------------------------
void CShip::OnReceiveClientUpdate( ClientSpaceWarUpdateData_t UpdateData )
{
if ( !m_bIsServerInstance )
{
OutputDebugString( "Should not be receiving client updates on non-server instances\n" );
return;
}
memcpy( &m_SpaceWarClientUpdateData, &UpdateData, sizeof( ClientSpaceWarUpdateData_t ) );
}
//-----------------------------------------------------------------------------
// Purpose: Tell the server about any updates we have had client-side
//-----------------------------------------------------------------------------
bool CShip::BGetClientUpdateData( ClientSpaceWarUpdateData_t *pUpdateData )
{
// Limit the rate at which we send updates, even if our internal frame rate is higher
if ( m_pGameEngine->GetGameTickCount() - m_ulLastClientUpdateTick < 1000.0f/CLIENT_UPDATE_SEND_RATE )
return false;
m_ulLastClientUpdateTick = m_pGameEngine->GetGameTickCount();
// Update playername before sending
if ( m_bIsLocalPlayer )
strncpy( m_SpaceWarClientUpdateData.m_rgchPlayerName, SteamFriends()->GetFriendPersonaName( SteamUser()->GetSteamID() ), ARRAYSIZE( m_SpaceWarClientUpdateData.m_rgchPlayerName ) );
memcpy( pUpdateData, &m_SpaceWarClientUpdateData, sizeof( ClientSpaceWarUpdateData_t ) );
memset( &m_SpaceWarClientUpdateData, 0, sizeof( m_SpaceWarClientUpdateData ) );
return true;
}
//-----------------------------------------------------------------------------
// Purpose: Get the name for this ship (only really works server side)
//-----------------------------------------------------------------------------
const char* CShip::GetPlayerName()
{
return m_SpaceWarClientUpdateData.m_rgchPlayerName;
}
//-----------------------------------------------------------------------------
// Purpose: Run a frame for the ship
//-----------------------------------------------------------------------------
void CShip::RunFrame()
{
if ( m_bDisabled )
return;
const uint64 ulCurrentTickCount = m_pGameEngine->GetGameTickCount();
// Look for expired photon beams
int nNextAvailablePhotonBeamSlot = -1; // Track next available slot for use spawning new beams below
for( int i=0; i < MAX_PHOTON_BEAMS_PER_SHIP; ++i )
{
if ( m_rgPhotonBeams[i] )
{
if ( m_rgPhotonBeams[i]->BIsBeamExpired() )
{
delete m_rgPhotonBeams[i];
m_rgPhotonBeams[i] = NULL;
}
}
if ( !m_rgPhotonBeams[i] && nNextAvailablePhotonBeamSlot == -1 )
nNextAvailablePhotonBeamSlot = i;
}
// run all the photon beams we have outstanding
for( int i=0; i < MAX_PHOTON_BEAMS_PER_SHIP; ++i )
{
if ( m_rgPhotonBeams[i] )
m_rgPhotonBeams[i]->RunFrame();
}
// run all the space debris
{
std::list<CShipDebris *>::iterator iter;
for( iter = m_ListDebris.begin(); iter != m_ListDebris.end(); ++iter )
(*iter)->RunFrame();
}
if ( m_bIsLocalPlayer )
{
m_SpaceWarClientUpdateData.m_bTurnLeftPressed = false;
m_SpaceWarClientUpdateData.m_bTurnRightPressed = false;
if ( m_pGameEngine->BIsKeyDown( m_dwVKLeft ) )
{
m_SpaceWarClientUpdateData.m_bTurnLeftPressed = true;
}
if ( m_pGameEngine->BIsKeyDown( m_dwVKRight ) )
{
m_SpaceWarClientUpdateData.m_bTurnRightPressed = true;
}
}
else if ( m_bIsServerInstance )
{
// Server side
float flRotationDelta = 0.0f;
if ( m_SpaceWarClientUpdateData.m_bTurnLeftPressed )
{
flRotationDelta += (PI_VALUE/2.0f) * -1.0f * (float)m_pGameEngine->GetGameTicksFrameDelta()/400.0f;
}
if ( m_SpaceWarClientUpdateData.m_bTurnRightPressed )
{
flRotationDelta += (PI_VALUE/2.0f) * (float)m_pGameEngine->GetGameTicksFrameDelta()/400.0f;
}
SetRotationDeltaNextFrame( flRotationDelta );
}
// Compute acceleration
if ( m_bIsLocalPlayer )
{
// client side
m_SpaceWarClientUpdateData.m_bReverseThrustersPressed = false;
m_SpaceWarClientUpdateData.m_bForwardThrustersPressed = false;
if ( m_pGameEngine->BIsKeyDown( m_dwVKForwardThrusters ) || m_pGameEngine->BIsKeyDown( m_dwVKReverseThrusters ) )
{
if ( m_pGameEngine->BIsKeyDown( m_dwVKReverseThrusters ) )
{
m_SpaceWarClientUpdateData.m_bReverseThrustersPressed = true;
}
else
{
m_SpaceWarClientUpdateData.m_bForwardThrustersPressed = true;
}
}
}
else if ( m_bIsServerInstance )
{
// Server side
float xThrust = 0;
float yThrust = 0;
m_bReverseThrustersActive = false;
m_bForwardThrustersActive = false;
if ( m_SpaceWarClientUpdateData.m_bReverseThrustersPressed || m_SpaceWarClientUpdateData.m_bForwardThrustersPressed )
{
float flSign = 1.0f;
if ( m_SpaceWarClientUpdateData.m_bReverseThrustersPressed )
{
m_bReverseThrustersActive = true;
flSign = -1.0f;
}
else
{
m_bForwardThrustersActive = true;
}
if ( m_ulLastThrustStartedTickCount == 0 )
m_ulLastThrustStartedTickCount = ulCurrentTickCount;
// You have to hold the key for a second to reach maximum thrust
float factor = min( ((float)(ulCurrentTickCount - m_ulLastThrustStartedTickCount) / 500.0f) + 0.2f, 1.0f );
xThrust = flSign * (float)(MAXIMUM_SHIP_THRUST * factor * sin( GetAccumulatedRotation() ) );
yThrust = flSign * -1.0f * (float)(MAXIMUM_SHIP_THRUST * factor * cos( GetAccumulatedRotation() ) );
}
else
{
m_ulLastThrustStartedTickCount = 0;
}
SetAcceleration( xThrust, yThrust );
}
// We'll use these values in a few places below to compute positions of child objects
// appropriately given our rotation
float sinvalue = (float)sin( GetAccumulatedRotation() );
float cosvalue = (float)cos( GetAccumulatedRotation() );
// See if we need to fire a photon beam
bool bFirePhotonBeam = m_bFirePhotonBeamNextFrame;
m_bFirePhotonBeamNextFrame = false;
if ( m_bIsLocalPlayer )
{
// client side
if ( m_pGameEngine->BIsKeyDown( m_dwVKFire ) )
{
m_SpaceWarClientUpdateData.m_bFirePressed = true;
}
}
else if ( m_bIsServerInstance )
{
// server side
if ( nNextAvailablePhotonBeamSlot != -1 && !m_bExploding && m_SpaceWarClientUpdateData.m_bFirePressed && ulCurrentTickCount - PHOTON_BEAM_FIRE_INTERVAL_TICKS > m_ulLastPhotonTickCount )
{
m_ulLastPhotonTickCount = ulCurrentTickCount;
float xVelocity = GetXVelocity() + ( sinvalue * 275 );
float yVelocity = GetYVelocity() - ( cosvalue * 275 );
// Offset 12 points up from the center of the ship, compensating for rotation
float xPos = GetXPos() - sinvalue*-12.0f;
float yPos = GetYPos() + cosvalue*-12.0f;
m_rgPhotonBeams[nNextAvailablePhotonBeamSlot] = new CPhotonBeam( m_pGameEngine, xPos, yPos, m_dwShipColor, GetAccumulatedRotation(), xVelocity, yVelocity );
}
}
CSpaceWarEntity::RunFrame();
// Finally, update the thrusters ( we do this after the base class call as they rely on our data being fully up-to-date)
m_ForwardThrusters.RunFrame();
m_ReverseThrusters.RunFrame();
}
//-----------------------------------------------------------------------------
// Purpose: Render the ship
//-----------------------------------------------------------------------------
void CShip::Render()
{
if ( m_bDisabled )
return;
// render all the photon beams we have outstanding
for( int i=0; i < MAX_PHOTON_BEAMS_PER_SHIP; ++i )
{
if ( m_rgPhotonBeams[i] )
m_rgPhotonBeams[i]->Render();
}
if ( m_bExploding )
{
// Don't draw actual ship, instead draw the pieces created in the explosion
std::list<CShipDebris *>::iterator iter;
for( iter = m_ListDebris.begin(); iter != m_ListDebris.end(); ++iter )
(*iter)->Render();
return;
}
// Check if we should be drawing thrusters
if ( m_bForwardThrustersActive )
{
if ( rand()%3 == 0 )
m_ForwardThrusters.Render();
}
if ( m_bReverseThrustersActive )
{
if ( rand()%3 == 0 )
m_ReverseThrusters.Render();
}
CSpaceWarEntity::Render();
}
//-----------------------------------------------------------------------------
// Purpose: Set whether the ship is exploding
//-----------------------------------------------------------------------------
void CShip::SetExploding( bool bExploding )
{
// If we are already in the specified state, no need to do the below work
if ( m_bExploding == bExploding )
return;
// Track that we are exploding, and disable collision detection
m_bExploding = bExploding;
SetCollisionDetectionDisabled( m_bExploding );
if ( bExploding )
{
for( int i = 0; i < SHIP_DEBRIS_PIECES; ++i )
{
CShipDebris * pDebris = new CShipDebris( m_pGameEngine, GetXPos(), GetYPos(), m_dwShipColor );
m_ListDebris.push_back( pDebris );
}
}
else
{
std::list<CShipDebris *>::iterator iter;
for( iter = m_ListDebris.begin(); iter != m_ListDebris.end(); ++iter )
delete *iter;
m_ListDebris.clear();
}
}
//-----------------------------------------------------------------------------
// Purpose: Check for photons which have hit the target and remove them
//-----------------------------------------------------------------------------
void CShip::DestroyPhotonsColldingWith( CVectorEntity *pTarget )
{
for( int i=0; i < MAX_PHOTON_BEAMS_PER_SHIP; ++i )
{
if ( !m_rgPhotonBeams[i] )
continue;
if ( m_rgPhotonBeams[i]->BCollidesWith( pTarget ) )
{
// Photon beam hit the entity, destroy beam
delete m_rgPhotonBeams[i];
m_rgPhotonBeams[i] = NULL;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Check whether any of the photons this ship has fired are colliding with the target
//-----------------------------------------------------------------------------
bool CShip::BCheckForPhotonsCollidingWith( CVectorEntity *pTarget )
{
for( int i=0; i < MAX_PHOTON_BEAMS_PER_SHIP; ++i )
{
if ( !m_rgPhotonBeams[i] )
continue;
if ( m_rgPhotonBeams[i]->BCollidesWith( pTarget ) )
{
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Build the update data to send from server to clients
//-----------------------------------------------------------------------------
void CShip::BuildServerUpdate( ServerShipUpdateData_t *pUpdateData )
{
pUpdateData->m_bDisabled = BIsDisabled();
pUpdateData->m_bExploding = BIsExploding();
pUpdateData->m_flXAcceleration = GetXAccelerationLastFrame();
pUpdateData->m_flYAcceleration = GetYAccelerationLastFrame();
pUpdateData->m_flXPosition = GetXPos();
pUpdateData->m_flYPosition = GetYPos();
pUpdateData->m_flXVelocity = GetXVelocity();
pUpdateData->m_flYVelocity = GetYVelocity();
pUpdateData->m_flCurrentRotation = GetAccumulatedRotation();
pUpdateData->m_flRotationDeltaLastFrame = GetRotationDeltaLastFrame();
pUpdateData->m_bForwardThrustersActive = m_bForwardThrustersActive;
pUpdateData->m_bReverseThrustersActive = m_bReverseThrustersActive;
BuildServerPhotonBeamUpdate( pUpdateData->m_PhotonBeamData );
}
//-----------------------------------------------------------------------------
// Purpose: Build the photon beam update data to send from the server to clients
//-----------------------------------------------------------------------------
void CShip::BuildServerPhotonBeamUpdate( ServerPhotonBeamUpdateData_t *pUpdateData )
{
for( int i = 0; i < MAX_PHOTON_BEAMS_PER_SHIP; ++i )
{
if ( m_rgPhotonBeams[i] )
{
pUpdateData[i].m_bIsActive = true;
pUpdateData[i].m_flXPosition = m_rgPhotonBeams[i]->GetXPos();
pUpdateData[i].m_flYPosition = m_rgPhotonBeams[i]->GetYPos();
pUpdateData[i].m_flXVelocity = m_rgPhotonBeams[i]->GetXVelocity();
pUpdateData[i].m_flYVelocity = m_rgPhotonBeams[i]->GetYVelocity();
pUpdateData[i].m_flCurrentRotation = m_rgPhotonBeams[i]->GetAccumulatedRotation();
}
else
{
pUpdateData[i].m_bIsActive = false;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Accumulate stats for this ship
//-----------------------------------------------------------------------------
void CShip::AccumulateStats( CStatsAndAchievements *pStats )
{
if ( m_bIsLocalPlayer )
{
pStats->AddDistanceTraveled( GetDistanceTraveledLastFrame() );
}
}
+197
View File
@@ -0,0 +1,197 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for rendering the player ships
//
// $NoKeywords: $
//=============================================================================
#ifndef SHIP_H
#define SHIP_H
#include <list>
#include "GameEngine.h"
#include "SpaceWarEntity.h"
#include "PhotonBeam.h"
#include "SpaceWar.h"
#define MAXIMUM_SHIP_THRUST 150
#define SHIP_DEBRIS_PIECES 6
// Forward declaration
class CShip;
class CSpaceWarServer;
class CStatsAndAchievements;
// Simple class for the ship thrusters
class CForwardThrusters : public CVectorEntity
{
public:
CForwardThrusters( CGameEngine *pGameEngine, CShip *pShip );
// Run Frame
void RunFrame();
private:
CShip *m_pShip;
};
// Again, but in reverse
class CReverseThrusters : public CVectorEntity
{
public:
CReverseThrusters( CGameEngine *pGameEngine, CShip *pShip );
// Run Frame
void RunFrame();
private:
CShip *m_pShip;
};
// Class to represent debris after explosion
class CShipDebris : public CSpaceWarEntity
{
public:
CShipDebris( CGameEngine *pGameEngine, float xPos, float yPos, DWORD dwDebrisColor );
// Run Frame
void RunFrame();
private:
// We keep the debris spinning
float m_flRotationPerInterval;
};
class CShip : public CSpaceWarEntity
{
public:
// Constructor
CShip( CGameEngine *pGameEngine, bool bIsServerInstance, float xPos, float yPos, DWORD dwShipColor );
// Destructor
~CShip();
// Run a frame
void RunFrame();
// Render a frame
void Render();
// Update ship with data from server
void OnReceiveServerUpdate( ServerShipUpdateData_t UpdateData );
// Update the ship with data from a client
void OnReceiveClientUpdate( ClientSpaceWarUpdateData_t UpdateData );
// Get the update data for this ship client side (copying into memory passed in)
bool BGetClientUpdateData( ClientSpaceWarUpdateData_t *pUpdatedata );
// Build update data for the ship to send to clients
void BuildServerUpdate( ServerShipUpdateData_t *pUpdateData );
// Build update data for photon beams to send to clients
void BuildServerPhotonBeamUpdate( ServerPhotonBeamUpdateData_t *pUpdateData );
// Reset vertex data for our object
void ResetVertexData();
// Set whether the ship is exploding
void SetExploding( bool bExploding );
// Set whether the ship is disabled
void SetDisabled( bool bDisabled ) { m_bDisabled = bDisabled; }
// Set the initial rotation for the ship
void SetInitialRotation( float flRotation ) { SetAccumulatedRotation( flRotation ); }
// Setters for key bindings
void SetVKBindingLeft( DWORD dwVKLeft ) { m_dwVKLeft = dwVKLeft; }
void SetVKBindingRight( DWORD dwVKRight ) { m_dwVKRight = dwVKRight; }
void SetVKBindingForwardThrusters( DWORD dwVKForward ) { m_dwVKForwardThrusters = dwVKForward; }
void SetVKBindingReverseThrusters( DWORD dwVKReverse ) { m_dwVKReverseThrusters = dwVKReverse; }
void SetVKBindingFire( DWORD dwVKFire ) { m_dwVKFire = dwVKFire; }
// Check for photons which have hit the entity and destroy the photons
void DestroyPhotonsColldingWith( CVectorEntity *pTarget );
// Check whether any of the photons this ship has fired are colliding with the target
bool BCheckForPhotonsCollidingWith( CVectorEntity *pTarget );
// Check if the ship is currently exploding
bool BIsExploding() { return m_bExploding; }
// Check if the ship is currently disabled
bool BIsDisabled() { return m_bDisabled; }
// Set whether this ship instance is for the local player
// (meaning it should pay attention to key input and such)
void SetIsLocalPlayer( bool bValue ) { m_bIsLocalPlayer = bValue; }
bool BIsLocalPlayer() { return m_bIsLocalPlayer; }
// Accumulate stats for this ship
void AccumulateStats( CStatsAndAchievements *pStats );
// Get the name for this ship (only really works server side)
const char* GetPlayerName();
private:
// Last time we sent an update on our local data to the server
uint64 m_ulLastClientUpdateTick;
// Last time we detected the thrust key go down
uint64 m_ulLastThrustStartedTickCount;
// Last time we fired a photon
uint64 m_ulLastPhotonTickCount;
// is this ship our local ship, or a remote player?
bool m_bIsLocalPlayer;
// Is this ship instance running inside the server (otherwise its a client...)
bool m_bIsServerInstance;
// is the ship exploding?
bool m_bExploding;
// is the ship disabled for now?
bool m_bDisabled;
// Do we need to fire a photon beam next frame?
bool m_bFirePhotonBeamNextFrame;
// vector of beams we have fired (in order of firing time)
CPhotonBeam * m_rgPhotonBeams[MAX_PHOTON_BEAMS_PER_SHIP];
// vector of debris to draw after an explosion
std::list< CShipDebris *> m_ListDebris;
// Color for this ship
DWORD m_dwShipColor;
// Thrusters for this ship
CForwardThrusters m_ForwardThrusters;
// Track whether to draw the thrusters next render call
bool m_bForwardThrustersActive;
// Thrusters for this ship
CReverseThrusters m_ReverseThrusters;
// Track whether to draw the thrusters next render call
bool m_bReverseThrustersActive;
// This will get populated only if we are the local instance, and then
// sent to the server in response to each server update
ClientSpaceWarUpdateData_t m_SpaceWarClientUpdateData;
// key bindings
DWORD m_dwVKLeft;
DWORD m_dwVKRight;
DWORD m_dwVKForwardThrusters;
DWORD m_dwVKReverseThrusters;
DWORD m_dwVKFire;
};
#endif // SHIP_H
+198
View File
@@ -0,0 +1,198 @@
//========= 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
// Current game server version
#define SPACEWAR_SERVER_VERSION "1.0.0.0"
// UDP port for the spacewar server to do authentication on (ie, talk to Steam on)
#define SPACEWAR_AUTHENTICATION_PORT 8766
// 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
// 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,
};
// Enum for possible game states on the server
enum EServerGameState
{
k_EServerWaitingForPlayers,
k_EServerActive,
k_EServerDraw,
k_EServerWinner,
k_EServerExiting,
};
// Data sent per photon beam from the server to update clients photon beam positions
struct ServerPhotonBeamUpdateData_t
{
// 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
{
// 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;
// Photon beam positions and data
ServerPhotonBeamUpdateData_t m_PhotonBeamData[MAX_PHOTON_BEAMS_PER_SHIP];
};
// This is the data that gets sent from the server to each client for each update
struct ServerSpaceWarUpdateData_t
{
// What state the game is in
EServerGameState 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
{
// Key's which are done
bool m_bFirePressed;
bool m_bTurnLeftPressed;
bool m_bTurnRightPressed;
bool m_bForwardThrustersPressed;
bool m_bReverseThrustersPressed;
// 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];
};
#endif // SPACEWAR_H
File diff suppressed because it is too large Load Diff
+284
View File
@@ -0,0 +1,284 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Main class for the space war game client
//
// $NoKeywords: $
//=============================================================================
#ifndef SPACEWARCLIENT_H
#define SPACEWARCLIENT_H
#include "GameEngine.h"
#include "SpaceWar.h"
#include "Messages.h"
#include "StarField.h"
#include "Sun.h"
#include "Ship.h"
#include "steam\steam_api.h"
#include "StatsAndAchievements.h"
#include "BaseMenu.h"
// Forward class declaration
class CMainMenu;
class CQuitMenu;
class CSpaceWarServer;
class CServerBrowser;
class CLobbyBrowser;
class CLobby;
// Height of the HUD font
#define HUD_FONT_HEIGHT 18
// Height for the instructions font
#define INSTRUCTIONS_FONT_HEIGHT 24
// Enum for various client connection states
enum EClientConnectionState
{
k_EClientNotConnected, // Initial state, not connected to a server
k_EClientConnectedPendingAuthentication, // We've established communication with the server, but it hasn't authed us yet
k_EClientConnectedAndAuthenticated, // Final phase, server has authed us, we are actually able to play on it
};
// a game server as shown in the find servers menu
struct ServerBrowserMenuData_t
{
EClientGameState m_eStateToTransitionTo;
uint32 m_unIPAddress;
int32 m_nConnectionPort;
};
// a lobby as shown in the find lobbies menu
struct LobbyBrowserMenuItem_t
{
CSteamID m_steamIDLobby;
EClientGameState m_eStateToTransitionTo;
};
// a user as shown in the lobby screen
struct LobbyMenuItem_t
{
CSteamID m_steamIDUser; // the user who this is in the lobby
bool m_bStartGame;
bool m_bToggleReadyState;
bool m_bLeaveLobby;
};
class CSpaceWarClient
{
public:
//Constructor
CSpaceWarClient( CGameEngine *pEngine, CSteamID steamIDUser );
// Destructor
~CSpaceWarClient();
// Run a game frame
void RunFrame();
// Checks for any incoming network data, then dispatches it
void ReceiveNetworkData();
// Connect to a server at a given IP address or game server steamID
void InitiateServerConnection( uint32 unServerAddress, const int32 nPort );
void InitiateServerConnection( CSteamID steamIDGameServer );
// Send data to a client at the given ship index
bool BSendServerData( char *pData, uint32 nSizeOfData, bool bSendReliably );
// Menu callback handler (handles a bunch of menus that just change state with no extra data)
void OnMenuSelection( EClientGameState eState ) { SetGameState( eState ); }
// Menu callback handler (handles server browser selections with extra data)
void OnMenuSelection( ServerBrowserMenuData_t selection )
{
if ( selection.m_eStateToTransitionTo == k_EClientGameConnecting )
{
InitiateServerConnection( selection.m_unIPAddress, selection.m_nConnectionPort );
}
else
{
SetGameState( selection.m_eStateToTransitionTo );
}
}
void OnMenuSelection( LobbyBrowserMenuItem_t selection )
{
// start joining the lobby
if ( selection.m_eStateToTransitionTo == k_EClientJoiningLobby )
{
SteamMatchmaking()->JoinLobby( selection.m_steamIDLobby );
// the callback LobbyEnter_t will be received when we've joined
}
SetGameState( selection.m_eStateToTransitionTo );
}
void OnMenuSelection( LobbyMenuItem_t selection );
// Set game state
void SetGameState( EClientGameState eState );
EClientGameState GetGameState() { return m_eGameState; }
// set failure text
void SetConnectionFailureText( const char *pchErrorText );
// Were we the winner?
bool BLocalPlayerWonLastGame();
// Get the steam id for the local user at this client
CSteamID GetLocalSteamID() { return m_SteamIDLocalUser; }
// Get the local players name
const char* GetLocalPlayerName() { return SteamFriends()->GetFriendPersonaName( m_SteamIDLocalUser ); }
// Scale screen size to "real" size
float PixelsToFeet( float flPixels );
// Get a Steam-supplied image
HGAMETEXTURE GetSteamImageAsTexture( int iImage );
private:
// Receive a response from the server for a connection attempt
void OnReceiveServerInfo( CSteamID steamIDGameServer, bool bVACSecure, const char *pchServerName );
// Receive a response from the server for a connection attempt
void OnReceiveServerAuthenticationResponse( bool bSuccess, uint32 uPlayerPosition );
// Receive a state update from the server
void OnReceiveServerUpdate( ServerSpaceWarUpdateData_t UpdateData );
// Handle the server exiting
void OnReceiveServerExiting();
// Disconnects from a server (telling it so) if we are connected
void DisconnectFromServer();
// game state changes
void OnGameStateChanged( EClientGameState eGameStateNew );
// Draw the HUD text (should do this after drawing all the objects)
void DrawHUDText();
// Draw instructions for how to play the game
void DrawInstructions();
// Draw text telling the players who won (or that their was a draw)
void DrawWinnerDrawOrWaitingText();
// Draw text telling the user that the connection attempt has failed
void DrawConnectionFailureText();
// Draw connect to server text
void DrawConnectToServerText();
// Draw text telling the user a connection attempt is in progress
void DrawConnectionAttemptText();
// Server we are connected to
CSpaceWarServer *m_pServer;
// SteamID for the local user on this client
CSteamID m_SteamIDLocalUser;
// Our ship position in the array below
uint32 m_uPlayerShipIndex;
// List of steamIDs for each player
CSteamID m_rgSteamIDPlayers[MAX_PLAYERS_PER_SERVER];
// Ships for players, doubles as a way to check for open slots (pointer is NULL meaning open)
CShip *m_rgpShips[MAX_PLAYERS_PER_SERVER];
// Player scores
uint32 m_rguPlayerScores[MAX_PLAYERS_PER_SERVER];
// Who just won the game? Should be set if we go into the k_EGameWinner state
uint32 m_uPlayerWhoWonGame;
// Current game state
EClientGameState m_eGameState;
// true if we only just transitioned state
bool m_bTransitionedGameState;
// Font handle for drawing the HUD text
HGAMEFONT m_hHUDFont;
// Font handle for drawing the instructions text
HGAMEFONT m_hInstructionsFont;
// Time the last state transition occurred (so we can count-down round restarts)
uint64 m_ulStateTransitionTime;
// Time we started our last connection attempt
uint64 m_ulLastConnectionAttemptRetryTime;
// Time we last got data from the server
uint64 m_ulLastNetworkDataReceivedTime;
// Text to display if we are in an error state
char m_rgchErrorText[256];
// Socket to use when communicating with servers
SNetSocket_t m_hSocketClient;
// Server address data
uint32 m_unServerIP;
uint16 m_usServerPort;
// Track whether we are connected to a server (and what specific state that connection is in)
EClientConnectionState m_eConnectedStatus;
// Star field instance
CStarField *m_pStarField;
// Sun instance
CSun *m_pSun;
// Main menu instance
CMainMenu *m_pMainMenu;
// Pause menu instance
CQuitMenu *m_pQuitMenu;
// pointer to game engine instance we are running under
CGameEngine *m_pGameEngine;
// track which steam image indexes we have textures for, and what handle that texture has
std::map<int, HGAMETEXTURE> m_MapSteamImagesToTextures;
CStatsAndAchievements *m_pStatsAndAchievements;
CServerBrowser *m_pServerBrowser;
// lobby handling
bool m_bCreatingLobby;
// the name of the lobby we're connected to
CSteamID m_steamIDLobby;
// callback for when we're creating a new lobby
STEAM_CALLBACK( CSpaceWarClient, OnLobbyCreated, LobbyCreated_t, m_LobbyCreatedCallback );
// callback for when we've joined a lobby
STEAM_CALLBACK( CSpaceWarClient, OnLobbyEntered, LobbyEnter_t, m_LobbyEnteredCallback );
// callback for when the lobby game server has started
STEAM_CALLBACK( CSpaceWarClient, OnLobbyGameCreated, LobbyGameCreated_t, m_LobbyGameCreated );
// lobby browser menu
CLobbyBrowser *m_pLobbyBrowser;
// local lobby display
CLobby *m_pLobby;
// connection handler
STEAM_CALLBACK( CSpaceWarClient, OnSocketStatusCallback, SocketStatusCallback_t, m_SocketStatusCallback );
};
extern CSpaceWarClient *g_pSpaceWarClient;
CSpaceWarClient *SpaceWarClient();
#endif // SPACEWARCLIENT_H
+53
View File
@@ -0,0 +1,53 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: A SpaceWarEntity is just like a VectorEntity, except it knows how
// to apply gravity from the SpaceWar Sun
//
// $NoKeywords: $
//=============================================================================
#include "stdafx.h"
#include "SpaceWarEntity.h"
#include "stdlib.h"
#include <math.h>
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CSpaceWarEntity::CSpaceWarEntity( CGameEngine *pGameEngine, uint32 uCollisionRadius, bool bAffectedByGravity )
: CVectorEntity( pGameEngine, uCollisionRadius )
{
m_bAffectedByGravity = bAffectedByGravity;
}
//-----------------------------------------------------------------------------
// Purpose: RunFrame
//-----------------------------------------------------------------------------
void CSpaceWarEntity::RunFrame()
{
if ( m_bAffectedByGravity )
{
float xAccel = GetXAcceleration();
float yAccel = GetYAcceleration();
// Ships are also affected by the suns gravity, compute that here, sun is always at the center of the screen
float xPosSun = (float)m_pGameEngine->GetViewportWidth()/2;
float yPosSun = (float)m_pGameEngine->GetViewportHeight()/2;
float distanceToSun = (float)sqrt( pow( xPosSun - GetXPos(), 2 ) + pow( yPosSun - GetYPos(), 2 ) );
float distancePower = (float)pow( distanceToSun, 2.0f ); // gravity power falls off exponentially
float factor = min( 5200000.0f / distancePower, 150.0f ); // arbitrary value for power of gravity
float xDirection = (GetXPos() - xPosSun)/distanceToSun;
float yDirection = (GetYPos() - yPosSun)/distanceToSun;
xAccel -= factor * xDirection;
yAccel -= factor * yDirection;
// Set updated acceleration
SetAcceleration( xAccel, yAccel );
}
CVectorEntity::RunFrame();
}
+31
View File
@@ -0,0 +1,31 @@
//========= Copyright Š 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: A SpaceWarEntity is just like a VectorEntity, except it knows how
// to apply gravity from the SpaceWar Sun
//
// $NoKeywords: $
//=============================================================================
#ifndef SPACEWARENTITY_H
#define SPACEWARENTITY_H
#include "GameEngine.h"
#include "VectorEntity.h"
class CSpaceWarEntity : public CVectorEntity
{
public:
// Constructor
CSpaceWarEntity( CGameEngine *pGameEngine, uint32 uCollisionRadius, bool bAffectedByGravity );
// Destructor
virtual ~CSpaceWarEntity() { return; }
// Run Frame
void RunFrame();
private:
bool m_bAffectedByGravity;
};
#endif // SPACEWARENTITY_H
File diff suppressed because it is too large Load Diff
+173
View File
@@ -0,0 +1,173 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Main class for the space war game server
//
// $NoKeywords: $
//=============================================================================
#ifndef SPACEWARSERVER_H
#define SPACEWARSERVER_H
#include "GameEngine.h"
#include "SpaceWar.h"
#include "Ship.h"
#include "Sun.h"
// Game server API code from Steam, lets us do authentication via Steam for who to allow to play,
// also lets us get ourselves listed in the Steam master server so the server browser can find us
#include "steam/steam_gameserver.h"
// Forward declaration
class CSpaceWarClient;
struct ClientConnectionData_t
{
bool m_bActive; // Is this slot in use? Or is it available for new connections?
SNetSocket_t m_hSocket; // Socket to send data on to get to this client
CSteamID m_SteamIDUser; // What is the steamid of the player?
uint64 m_ulTickCountLastData; // What was the last time we got data from the player?
};
class CSpaceWarServer
{
public:
//Constructor
CSpaceWarServer( CGameEngine *pEngine );
// Destructor
~CSpaceWarServer();
// Run a game frame
void RunFrame();
// Set game state
void SetGameState( EServerGameState eState );
// Reset player scores (occurs when starting a new game)
void ResetScores();
// Reset player positions (occurs in between rounds as well as at the start of a new game)
void ResetPlayerShips();
// Checks various game objects for collisions and updates state appropriately if they have occurred
void CheckForCollisions();
// data accessors
bool IsConnectedToSteam() { return m_bConnectedToSteam; }
uint32 GetIP();
uint16 GetPort();
CSteamID GetSteamID();
private:
//
// Various callback functions that Steam will call to let us know about events related to our
// connection to the Steam servers for authentication purposes.
//
// Tells us when we have successfully connected to Steam
STEAM_GAMESERVER_CALLBACK( CSpaceWarServer, OnSteamServersConnected, SteamServersConnected_t, m_CallbackSteamServersConnected );
// Tells us when we have been logged out of Steam
STEAM_GAMESERVER_CALLBACK( CSpaceWarServer, OnSteamServersDisconnected, SteamServersDisconnected_t, m_CallbackSteamServersDisconnected );
// Tells us that Steam has set our security policy (VAC on or off)
STEAM_GAMESERVER_CALLBACK( CSpaceWarServer, OnPolicyResponse, GSPolicyResponse_t, m_CallbackPolicyResponse );
//
// Various callback functions that Steam will call to let us know about whether we should
// allow clients to play or we should kick/deny them.
//
// Tells us a client has been authenticated and approved to play by Steam (passes auth, license check, VAC status, etc...)
STEAM_GAMESERVER_CALLBACK( CSpaceWarServer, OnGSClientApprove, GSClientApprove_t, m_CallbackGSClientApprove );
// Tells us we should deny a player from accessing the server
STEAM_GAMESERVER_CALLBACK( CSpaceWarServer, OnGSClientDeny, GSClientDeny_t, m_CallbackGSClientDeny );
// Tells us we should kick a player who was previously allowed to play (maybe they are no longer connected
// to steam so their VAC status cannot be verified)
STEAM_GAMESERVER_CALLBACK( CSpaceWarServer, OnGSClientKick, GSClientKick_t, m_CallbackGSClientKick );
// client connection state
STEAM_GAMESERVER_CALLBACK( CSpaceWarServer, OnSocketStatusCallback, SocketStatusCallback_t, m_CallbackSocketStatus );
// Function to tell Steam about our servers details
void SendUpdatedServerDetailsToSteam();
// Receive updates from client
void OnReceiveClientUpdateData( uint32 uShipIndex, ClientSpaceWarUpdateData_t UpdateData );
// Checks for any incoming network data, then dispatches it
void ReceiveNetworkData();
// Send data to a client at the given ship index
bool BSendDataToClient( uint32 uShipIndex, char *pData, uint32 nSizeOfData );
// Send data to a client at the given pending index
bool BSendDataToPendingClient( uint32 uShipIndex, char *pData, uint32 nSizeOfData );
// Send data to a client at a given address
bool BSendDataToClientOnSocket( SNetSocket_t hSocket, char *pData, uint32 nSizeOfData );
// Connect a client, will send a success/failure response to the client
void OnClientBeginAuthentication( SNetSocket_t hSocketClient, CSteamID steamIDUser, void *pToken, uint32 uTokenLen );
// Handles authentication completing for a client
void OnAuthCompleted( bool bAuthSuccess, uint32 iPendingAuthIndex );
// Adds/initializes a new player ship at the given position
void AddPlayerShip( uint32 uShipPosition );
// Removes a player from the server
void RemovePlayerFromServer( uint32 uShipPosition );
// Send world update to all clients
void SendUpdateDataToAllClients();
// Track whether our server is connected to Steam ok (meaning we can restrict who plays based on
// ownership and VAC bans, etc...)
bool m_bConnectedToSteam;
// Ships for players, doubles as a way to check for open slots (pointer is NULL meaning open)
CShip *m_rgpShips[MAX_PLAYERS_PER_SERVER];
// Player scores
uint32 m_rguPlayerScores[MAX_PLAYERS_PER_SERVER];
// server name
std::string m_sServerName;
// Who just won the game? Should be set if we go into the k_EGameWinner state
uint32 m_uPlayerWhoWonGame;
// Last time state changed
uint64 m_ulStateTransitionTime;
// Last time we sent clients an update
uint64 m_ulLastServerUpdateTick;
// Number of players currently connected, updated each frame
uint32 m_uPlayerCount;
// Current game state
EServerGameState m_eGameState;
// Sun instance
CSun *m_pSun;
// Server socket (which has been bound to our known port)
SNetSocket_t m_hSocketServer;
// pointer to game engine instance we are running under
CGameEngine *m_pGameEngine;
// Vector to keep track of client connections
ClientConnectionData_t m_rgClientData[MAX_PLAYERS_PER_SERVER];
// Vector to keep track of client connections which are pending auth
ClientConnectionData_t m_rgPendingClientData[MAX_PLAYERS_PER_SERVER];
};
#endif // SPACEWARSERVER_H
+50
View File
@@ -0,0 +1,50 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for rendering the starfield
//
// $NoKeywords: $
//=============================================================================
#include "stdafx.h"
#include "StarField.h"
#include "stdlib.h"
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CStarField::CStarField( CGameEngine *pGameEngine )
{
m_pGameEngine = pGameEngine;
StarVertex_t StarVertex;
int32 width = pGameEngine->GetViewportWidth();
int32 height = pGameEngine->GetViewportHeight();
// Generate star field data
for( int i=0; i < STARFIELD_STAR_COUNT; ++i )
{
int32 nRand = (rand()%(255-50))+50; //value between 50 and 255 for shades of gray
StarVertex.color = D3DCOLOR_ARGB( 255, nRand, nRand, nRand );
StarVertex.x = (float)(rand()%width);
StarVertex.y = (float)(rand()%height);
m_VecStars.push_back( StarVertex );
// bugbug jmccaskey - sometimes make "big stars" which are 4 points right next to each other?
}
}
//-----------------------------------------------------------------------------
// Purpose: Render the star field
//-----------------------------------------------------------------------------
void CStarField::Render()
{
for( size_t i = 0; i < m_VecStars.size(); ++i )
{
m_pGameEngine->BDrawPoint( m_VecStars[i].x, m_VecStars[i].y, m_VecStars[i].color );
}
m_pGameEngine->BFlushPointBuffer();
}
+40
View File
@@ -0,0 +1,40 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for rendering the starfield
//
// $NoKeywords: $
//=============================================================================
#ifndef STARFIELD_H
#define STARFIELD_H
#include <vector>
#include "GameEngine.h"
#define STARFIELD_STAR_COUNT 600
struct StarVertex_t
{
float x, y;
DWORD color;
};
class CStarField
{
public:
// Constructor
CStarField( CGameEngine *pGameEngine );
// Render the star field
void Render();
private:
// Game engine instance we are running under
CGameEngine *m_pGameEngine;
// Vector for starfield data
std::vector<StarVertex_t> m_VecStars;
};
#endif // STARFIELD_H
+519
View File
@@ -0,0 +1,519 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for tracking stats and achievements
//
// $NoKeywords: $
//=============================================================================
#include "stdafx.h"
#include "StatsAndAchievements.h"
#include <math.h>
#include "steam/isteamuserstats.h"
#include "SpaceWarClient.h"
#define ACHDISP_FONT_HEIGHT 20
#define ACHDISP_COLUMN_WIDTH 340
#define ACHDISP_CENTER_SPACING 40
#define ACHDISP_VERT_SPACING 10
#define ACHDISP_IMG_SIZE 64
#define ACHDISP_IMG_PAD 10
#define _ACH_ID( id, name ) { id, #id, name, "", 0, 0 }
Achievement_t g_rgAchievements[] =
{
_ACH_ID( ACH_WIN_ONE_GAME, "Winner" ),
_ACH_ID( ACH_WIN_100_GAMES, "Champion" ),
_ACH_ID( ACH_TRAVEL_FAR_ACCUM, "Interstellar" ),
_ACH_ID( ACH_TRAVEL_FAR_SINGLE, "Orbiter" ),
};
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
#pragma warning( push )
// warning C4355: 'this' : used in base member initializer list
// This is OK because it's warning on setting up the Steam callbacks, they won't use this until after construction is done
#pragma warning( disable : 4355 )
CStatsAndAchievements::CStatsAndAchievements( CGameEngine *pGameEngine )
:
m_pGameEngine( pGameEngine ),
m_pSteamUser( NULL ),
m_pSteamUserStats( NULL ),
m_GameID( SteamUtils()->GetAppID() ),
m_CallbackUserStatsReceived( this, &CStatsAndAchievements::OnUserStatsReceived ),
m_CallbackUserStatsStored( this, &CStatsAndAchievements::OnUserStatsStored ),
m_CallbackAchievementStored( this, &CStatsAndAchievements::OnAchievementStored )
{
m_pSteamUser = SteamUser();
m_pSteamUserStats = SteamUserStats();
m_bRequestedStats = false;
m_bStatsValid = false;
m_bStoreStats = false;
m_flGameFeetTraveled = 0;
m_nTotalGamesPlayed = 0;
m_nTotalNumWins = 0;
m_nTotalNumLosses = 0;
m_flTotalFeetTraveled = 0;
m_flMaxFeetTraveled = 0;
m_flAverageSpeed = 0;
m_hDisplayFont = pGameEngine->HCreateFont( ACHDISP_FONT_HEIGHT, FW_MEDIUM, false, "Arial" );
if ( !m_hDisplayFont )
OutputDebugString( "Stats font was not created properly, text won't draw\n" );
}
#pragma warning( pop )
//-----------------------------------------------------------------------------
// Purpose: Run a frame for the CStatsAndAchievements
//-----------------------------------------------------------------------------
void CStatsAndAchievements::RunFrame()
{
if ( !m_bRequestedStats )
{
// Is Steam Loaded? if no, can't get stats, done
if ( NULL == m_pSteamUserStats || NULL == m_pSteamUser )
{
m_bRequestedStats = true;
return;
}
// If yes, are we connected to the back end? if no, wait
if ( !m_pSteamUser->BLoggedOn() )
{
return;
}
// If yes, request our stats
bool bSuccess = m_pSteamUserStats->RequestCurrentStats( );
// This function should only return false if we weren't logged in, and we already checked that.
// But handle it being false again anyway, just ask again later.
m_bRequestedStats = bSuccess;
}
if ( !m_bStatsValid )
return;
// Get info from sources
// Evaluate achievements
for ( int iAch = 0; iAch < ARRAYSIZE( g_rgAchievements ); ++iAch )
{
EvaluateAchievement( g_rgAchievements[iAch] );
}
// Store stats
StoreStatsIfNecessary();
}
//-----------------------------------------------------------------------------
// Purpose: Accumulate distance traveled
//-----------------------------------------------------------------------------
void CStatsAndAchievements::AddDistanceTraveled( float flDistance )
{
m_flGameFeetTraveled += SpaceWarClient()->PixelsToFeet( flDistance );
}
//-----------------------------------------------------------------------------
// Purpose: Game state has changed
//-----------------------------------------------------------------------------
void CStatsAndAchievements::OnGameStateChange( EClientGameState eNewState )
{
if ( !m_bStatsValid )
return;
switch ( eNewState )
{
case k_EClientStatsAchievements:
case k_EClientGameStartServer:
case k_EClientGameMenu:
case k_EClientGameQuitMenu:
case k_EClientGameExiting:
case k_EClientGameInstructions:
case k_EClientGameConnecting:
case k_EClientGameConnectionFailure:
default:
break;
case k_EClientGameActive:
// Reset per-game stats
m_flGameFeetTraveled = 0;
m_ulTickCountGameStart = m_pGameEngine->GetGameTickCount();
break;
case k_EClientFindInternetServers:
break;
case k_EClientGameWinner:
if ( SpaceWarClient()->BLocalPlayerWonLastGame() )
m_nTotalNumWins++;
else
m_nTotalNumLosses++;
// fall through
case k_EClientGameDraw:
// Tally games
m_nTotalGamesPlayed++;
// Accumulate distances
m_flTotalFeetTraveled += m_flGameFeetTraveled;
// New max?
if ( m_flGameFeetTraveled > m_flMaxFeetTraveled )
m_flMaxFeetTraveled = m_flGameFeetTraveled;
// Calc game duration
m_flGameDurationSeconds = ( m_pGameEngine->GetGameTickCount() - m_ulTickCountGameStart ) / 1000.0;
// We want to update stats the next frame.
m_bStoreStats = true;
break;
}
}
//-----------------------------------------------------------------------------
// Purpose: see if we should unlock this achievement
//-----------------------------------------------------------------------------
void CStatsAndAchievements::EvaluateAchievement( Achievement_t &achievement )
{
// Already have it?
if ( achievement.m_bAchieved )
return;
switch ( achievement.m_eAchievementID )
{
case ACH_WIN_ONE_GAME:
if ( m_nTotalNumWins )
{
UnlockAchievement( achievement );
}
break;
case ACH_WIN_100_GAMES:
if ( m_nTotalNumWins >= 100 )
{
UnlockAchievement( achievement );
}
break;
case ACH_TRAVEL_FAR_ACCUM:
if ( m_flTotalFeetTraveled >= 5280 )
{
UnlockAchievement( achievement );
}
break;
case ACH_TRAVEL_FAR_SINGLE:
if ( m_flGameFeetTraveled > 500 )
{
UnlockAchievement( achievement );
}
break;
}
}
//-----------------------------------------------------------------------------
// Purpose: Unlock this achievement
//-----------------------------------------------------------------------------
void CStatsAndAchievements::UnlockAchievement( Achievement_t &achievement )
{
achievement.m_bAchieved = true;
// the icon may change once it's unlocked
achievement.m_iIconImage = 0;
// mark it down
m_pSteamUserStats->SetAchievement( achievement.m_pchAchievementID );
// Store stats end of frame
m_bStoreStats = true;
}
//-----------------------------------------------------------------------------
// Purpose: Store stats in the Steam database
//-----------------------------------------------------------------------------
void CStatsAndAchievements::StoreStatsIfNecessary()
{
if ( m_bStoreStats )
{
// already set any achievements in UnlockAchievement
// set stats
m_pSteamUserStats->SetStat( "NumGames", m_nTotalGamesPlayed );
m_pSteamUserStats->SetStat( "NumWins", m_nTotalNumWins );
m_pSteamUserStats->SetStat( "NumLosses", m_nTotalNumLosses );
m_pSteamUserStats->SetStat( "FeetTraveled", m_flTotalFeetTraveled );
m_pSteamUserStats->SetStat( "MaxFeetTraveled", m_flMaxFeetTraveled );
// Update average feet / second stat
m_pSteamUserStats->UpdateAvgRateStat( "AverageSpeed", m_flGameFeetTraveled, m_flGameDurationSeconds );
// The averaged result is calculated for us
m_pSteamUserStats->GetStat( "AverageSpeed", &m_flAverageSpeed );
bool bSuccess = m_pSteamUserStats->StoreStats();
// If this failed, we never sent anything to the server, try
// again later.
m_bStoreStats = !bSuccess;
}
}
//-----------------------------------------------------------------------------
// Purpose: We have stats data from Steam. It is authoritative, so update
// our data with those results now.
//-----------------------------------------------------------------------------
void CStatsAndAchievements::OnUserStatsReceived( UserStatsReceived_t *pCallback )
{
if ( !m_pSteamUserStats )
return;
// we may get callbacks for other games' stats arriving, ignore them
if ( m_GameID.ToUint64() == pCallback->m_nGameID )
{
if ( k_EResultOK == pCallback->m_eResult )
{
OutputDebugString( "Received stats and achievements from Steam\n" );
m_bStatsValid = true;
// load achievements
for ( int iAch = 0; iAch < ARRAYSIZE( g_rgAchievements ); ++iAch )
{
Achievement_t &ach = g_rgAchievements[iAch];
m_pSteamUserStats->GetAchievement( ach.m_pchAchievementID, &ach.m_bAchieved );
_snprintf( ach.m_rgchName, sizeof( ach.m_rgchName ), "%s",
m_pSteamUserStats->GetAchievementDisplayAttribute( ach.m_pchAchievementID, "name" ) );
_snprintf( ach.m_rgchDescription, sizeof( ach.m_rgchDescription ), "%s",
m_pSteamUserStats->GetAchievementDisplayAttribute( ach.m_pchAchievementID, "desc" ) );
}
// load stats
m_pSteamUserStats->GetStat( "NumGames", &m_nTotalGamesPlayed );
m_pSteamUserStats->GetStat( "NumWins", &m_nTotalNumWins );
m_pSteamUserStats->GetStat( "NumLosses", &m_nTotalNumLosses );
m_pSteamUserStats->GetStat( "FeetTraveled", &m_flTotalFeetTraveled );
m_pSteamUserStats->GetStat( "MaxFeetTraveled", &m_flMaxFeetTraveled );
m_pSteamUserStats->GetStat( "AverageSpeed", &m_flAverageSpeed );
}
else
{
char buffer[128];
_snprintf( buffer, 128, "RequestStats - failed, %d\n", pCallback->m_eResult );
OutputDebugString( buffer );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Our stats data was stored!
//-----------------------------------------------------------------------------
void CStatsAndAchievements::OnUserStatsStored( UserStatsStored_t *pCallback )
{
// we may get callbacks for other games' stats arriving, ignore them
if ( m_GameID.ToUint64() == pCallback->m_nGameID )
{
if ( k_EResultOK == pCallback->m_eResult )
{
OutputDebugString( "StoreStats - success\n" );
}
else
{
char buffer[128];
_snprintf( buffer, 128, "StoreStats - failed, %d\n", pCallback->m_eResult );
OutputDebugString( buffer );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: An achievement was stored
//-----------------------------------------------------------------------------
void CStatsAndAchievements::OnAchievementStored( UserAchievementStored_t *pCallback )
{
// we may get callbacks for other games' stats arriving, ignore them
if ( m_GameID.ToUint64() == pCallback->m_nGameID )
{
if ( 0 == pCallback->m_nMaxProgress )
{
char buffer[128];
_snprintf( buffer, 128, "Achievement '%s' unlocked!", pCallback->m_rgchAchievementName );
OutputDebugString( buffer );
}
else
{
char buffer[128];
_snprintf( buffer, 128, "Achievement '%s' progress callback, (%d,%d)\n",
pCallback->m_rgchAchievementName, pCallback->m_nCurProgress, pCallback->m_nMaxProgress );
OutputDebugString( buffer );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Display the user's stats and achievements
//-----------------------------------------------------------------------------
void CStatsAndAchievements::Render()
{
const int32 width = m_pGameEngine->GetViewportWidth();
const int32 height = m_pGameEngine->GetViewportHeight();
const int32 pxColumn1Left = width / 2 - ACHDISP_COLUMN_WIDTH - ACHDISP_CENTER_SPACING / 2;
const int32 pxColumn2Left = width / 2 + ACHDISP_CENTER_SPACING / 2;
RECT rect;
if ( !m_bStatsValid )
{
rect.top = 0;
rect.bottom = m_pGameEngine->GetViewportHeight();
rect.left = 0;
rect.right = width;
char rgchBuffer[256];
_snprintf( rgchBuffer, sizeof( rgchBuffer), "Unable to retrieve data from Steam\n" );
m_pGameEngine->BDrawString( m_hDisplayFont, rect, D3DCOLOR_ARGB( 255, 25, 200, 25 ), DT_CENTER|DT_VCENTER, rgchBuffer );
rect.left = 0;
rect.right = width;
rect.top = LONG(m_pGameEngine->GetViewportHeight() * 0.7);
rect.bottom = m_pGameEngine->GetViewportHeight();
_snprintf( rgchBuffer, sizeof( rgchBuffer ), "Press ESC to return to the Main Menu" );
m_pGameEngine->BDrawString( m_hDisplayFont, rect, D3DCOLOR_ARGB( 255, 25, 200, 25 ), DT_CENTER|DT_TOP, rgchBuffer );
}
else
{
// COLUMN 1
// Achievements above the midline
int32 pxVertOffset = height / 2 - 2 * ( ACHDISP_IMG_SIZE + ACHDISP_VERT_SPACING );
rect.top = pxVertOffset;
rect.bottom = rect.top + ACHDISP_IMG_SIZE;
rect.left = pxColumn1Left;
rect.right = rect.left + ACHDISP_COLUMN_WIDTH;
pxVertOffset = rect.bottom + ACHDISP_VERT_SPACING;
DrawAchievementInfo( rect, g_rgAchievements[0] );
rect.top = pxVertOffset;
rect.bottom = rect.top + ACHDISP_IMG_SIZE;
pxVertOffset = rect.bottom + ACHDISP_VERT_SPACING;
DrawAchievementInfo( rect, g_rgAchievements[1] );
// Stats below the midline
pxVertOffset = height / 2 + ACHDISP_VERT_SPACING;
rect.top = pxVertOffset;
rect.bottom = rect.top + ACHDISP_FONT_HEIGHT;
pxVertOffset = rect.bottom + ACHDISP_VERT_SPACING;
DrawStatInfo( rect, "Games Played", static_cast<float>( m_nTotalGamesPlayed ) );
rect.top = pxVertOffset;
rect.bottom = rect.top + ACHDISP_FONT_HEIGHT;
pxVertOffset = rect.bottom + ACHDISP_VERT_SPACING;
DrawStatInfo( rect, "Games Won", static_cast<float>( m_nTotalNumWins ) );
rect.top = pxVertOffset;
rect.bottom = rect.top + ACHDISP_FONT_HEIGHT;
pxVertOffset = rect.bottom + ACHDISP_VERT_SPACING;
DrawStatInfo( rect, "Games Lost", static_cast<float>( m_nTotalNumLosses ) );
// COLUMN 2
// Achievements above the midline
pxVertOffset = height / 2 - 2 * ( ACHDISP_IMG_SIZE + ACHDISP_VERT_SPACING );
rect.top = pxVertOffset;
rect.bottom = rect.top + ACHDISP_IMG_SIZE;
rect.left = pxColumn2Left;
rect.right = rect.left + ACHDISP_COLUMN_WIDTH;
pxVertOffset = rect.bottom + ACHDISP_VERT_SPACING;
DrawAchievementInfo( rect, g_rgAchievements[2] );
rect.top = pxVertOffset;
rect.bottom = rect.top + ACHDISP_IMG_SIZE;
pxVertOffset = rect.bottom + ACHDISP_VERT_SPACING;
DrawAchievementInfo( rect, g_rgAchievements[3] );
// Stats below the midline
pxVertOffset = height / 2 + ACHDISP_VERT_SPACING;
rect.top = pxVertOffset;
rect.bottom = rect.top + ACHDISP_FONT_HEIGHT;
pxVertOffset = rect.bottom + ACHDISP_VERT_SPACING;
DrawStatInfo( rect, "Feet Traveled", m_flTotalFeetTraveled );
rect.top = pxVertOffset;
rect.bottom = rect.top + ACHDISP_FONT_HEIGHT;
pxVertOffset = rect.bottom + ACHDISP_VERT_SPACING;
DrawStatInfo( rect, "Max Feet Traveled", m_flMaxFeetTraveled );
rect.top = pxVertOffset;
rect.bottom = rect.top + ACHDISP_FONT_HEIGHT;
pxVertOffset = rect.bottom + ACHDISP_VERT_SPACING;
DrawStatInfo( rect, "Average Inches / Second", m_flAverageSpeed * 12.0f );
// Footer
rect.left = 0;
rect.right = width;
rect.top = LONG(m_pGameEngine->GetViewportHeight() * 0.7);
rect.bottom = m_pGameEngine->GetViewportHeight();
char rgchBuffer[256];
_snprintf( rgchBuffer, sizeof( rgchBuffer ), "Press ESC to return to the Main Menu" );
m_pGameEngine->BDrawString( m_hDisplayFont, rect, D3DCOLOR_ARGB( 255, 25, 200, 25 ), DT_CENTER|DT_TOP, rgchBuffer );
}
}
void CStatsAndAchievements::DrawAchievementInfo( RECT &rect, Achievement_t &ach )
{
if ( ach.m_iIconImage == 0 )
{
ach.m_iIconImage = m_pSteamUserStats->GetAchievementIcon( ach.m_pchAchievementID );
}
HGAMETEXTURE hTexture = SpaceWarClient()->GetSteamImageAsTexture( ach.m_iIconImage );
// don't modify the caller's rect, they may use it later to locate something else
RECT rect2 = rect;
// could still be zero if the image isn't downloaded yet
if (hTexture )
{
m_pGameEngine->BDrawTexturedQuad( (float)rect2.left, (float)rect2.top, (float)rect2.left+ACHDISP_IMG_SIZE, (float)rect2.bottom,
0.0f, 0.0f, 1.0, 1.0, D3DCOLOR_ARGB( 255, 255, 255, 255 ), hTexture );
rect2.left += ACHDISP_IMG_SIZE + ACHDISP_IMG_PAD;
}
// todo: divide up so can draw image
char rgchBuffer[256];
_snprintf( rgchBuffer, sizeof( rgchBuffer), "%s: %s\n%s",
ach.m_rgchName,
ach.m_bAchieved ? "Unlocked" : "Locked",
ach.m_rgchDescription );
m_pGameEngine->BDrawString( m_hDisplayFont, rect2, D3DCOLOR_ARGB( 255, 25, 200, 25 ), DT_LEFT|DT_VCENTER, rgchBuffer );
}
void CStatsAndAchievements::DrawStatInfo( RECT &rect, const char *pchName, float flValue )
{
// todo: divide up so can draw image
char rgchBuffer[256];
_snprintf( rgchBuffer, sizeof( rgchBuffer), "%s: %.1f", pchName, flValue );
m_pGameEngine->BDrawString( m_hDisplayFont, rect, D3DCOLOR_ARGB( 255, 25, 200, 25 ), DT_LEFT|DT_VCENTER, rgchBuffer );
}
+108
View File
@@ -0,0 +1,108 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for tracking stats and achievements
//
// $NoKeywords: $
//=============================================================================
#ifndef STATS_AND_ACHIEVEMENTS_H
#define STATS_AND_ACHIEVEMENTS_H
#include "SpaceWar.h"
#include "GameEngine.h"
#include "steam/isteamuserstats.h"
enum EAchievements
{
ACH_WIN_ONE_GAME = 0,
ACH_WIN_100_GAMES = 1,
ACH_HEAVY_FIRE = 2,
ACH_TRAVEL_FAR_ACCUM = 3,
ACH_TRAVEL_FAR_SINGLE = 4,
};
struct Achievement_t
{
EAchievements m_eAchievementID;
const char *m_pchAchievementID;
char m_rgchName[128];
char m_rgchDescription[256];
bool m_bAchieved;
int m_iIconImage;
};
class ISteamUser;
class CSpaceWarClient;
class CStatsAndAchievements
{
public:
// Constructor
CStatsAndAchievements( CGameEngine *pGameEngine );
// Run a frame
void RunFrame();
// Display the stats and achievements
void Render();
// Game state changed
void OnGameStateChange( EClientGameState eNewState );
// Accumulators
void AddDistanceTraveled( float flDistance );
STEAM_CALLBACK( CStatsAndAchievements, OnUserStatsReceived, UserStatsReceived_t, m_CallbackUserStatsReceived );
STEAM_CALLBACK( CStatsAndAchievements, OnUserStatsStored, UserStatsStored_t, m_CallbackUserStatsStored );
STEAM_CALLBACK( CStatsAndAchievements, OnAchievementStored, UserAchievementStored_t, m_CallbackAchievementStored );
private:
// Determine if we get this achievement now
void EvaluateAchievement( Achievement_t &achievement );
void UnlockAchievement( Achievement_t &achievement );
// Store stats
void StoreStatsIfNecessary();
// Render helpers
void DrawAchievementInfo( RECT &rect, Achievement_t &ach );
void DrawStatInfo( RECT &rect, const char *pchName, float flValue );
// our GameID
CGameID m_GameID;
// Engine
CGameEngine *m_pGameEngine;
// Steam User interface
ISteamUser *m_pSteamUser;
// Steam UserStats interface
ISteamUserStats *m_pSteamUserStats;
// Display font
HGAMEFONT m_hDisplayFont;
// Did we get the stats from Steam?
bool m_bRequestedStats;
bool m_bStatsValid;
// Should we store stats this frame?
bool m_bStoreStats;
// Current Stat details
float m_flGameFeetTraveled;
uint64 m_ulTickCountGameStart;
double m_flGameDurationSeconds;
// Persisted Stat details
int m_nTotalGamesPlayed;
int m_nTotalNumWins;
int m_nTotalNumLosses;
float m_flTotalFeetTraveled;
float m_flMaxFeetTraveled;
float m_flAverageSpeed;
};
#endif // STATS_AND_ACHIEVEMENTS_H
+20
View File
@@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SteamworksExample", "SteamworksExample.vcproj", "{F9B80FD0-A31F-443F-9FFF-85813D209141}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F9B80FD0-A31F-443F-9FFF-85813D209141}.Debug|Win32.ActiveCfg = Debug|Win32
{F9B80FD0-A31F-443F-9FFF-85813D209141}.Debug|Win32.Build.0 = Debug|Win32
{F9B80FD0-A31F-443F-9FFF-85813D209141}.Release|Win32.ActiveCfg = Release|Win32
{F9B80FD0-A31F-443F-9FFF-85813D209141}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
+360
View File
@@ -0,0 +1,360 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="SteamworksExample"
ProjectGUID="{F9B80FD0-A31F-443F-9FFF-85813D209141}"
RootNamespace="SteamWorksExample"
SccProvider="MSSCCI:Perforce SCM"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory=".\$(ConfigurationName)"
IntermediateDirectory=".\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="0"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
CommandLine="copy ..\redistributable_bin\steam_api.dll .\$(ConfigurationName)\steam_api.dll&#x0D;&#x0A;"
Outputs=".\$(ConfigurationName)\steam_api.dll"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\public;"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS"
MinimalRebuild="true"
ExceptionHandling="2"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="steam_api.lib"
LinkIncremental="2"
AdditionalLibraryDirectories="..\redistributable_bin;"
GenerateDebugInformation="true"
SubSystem="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory=".\$(ConfigurationName)"
IntermediateDirectory=".\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="0"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
CommandLine="copy ..\redistributable_bin\steam_api.dll .\$(ConfigurationName)\steam_api.dll&#x0D;&#x0A;"
Outputs=".\$(ConfigurationName)\steam_api.dll"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\public;"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS"
ExceptionHandling="2"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="steam_api.lib"
LinkIncremental="1"
AdditionalLibraryDirectories="..\redistributable_bin;"
GenerateDebugInformation="true"
SubSystem="2"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\Main.cpp"
>
</File>
<File
RelativePath=".\stdafx.cpp"
>
</File>
<Filter
Name="Engine"
>
<File
RelativePath=".\GameEngine.cpp"
>
</File>
<File
RelativePath=".\VectorEntity.cpp"
>
</File>
</Filter>
<Filter
Name="Game"
>
<File
RelativePath=".\BaseMenu.cpp"
>
</File>
<File
RelativePath=".\Lobby.cpp"
>
</File>
<File
RelativePath=".\MainMenu.cpp"
>
</File>
<File
RelativePath=".\PhotonBeam.cpp"
>
</File>
<File
RelativePath=".\QuitMenu.cpp"
>
</File>
<File
RelativePath=".\ServerBrowser.cpp"
>
</File>
<File
RelativePath=".\Ship.cpp"
>
</File>
<File
RelativePath=".\SpaceWarClient.cpp"
>
</File>
<File
RelativePath=".\SpaceWarEntity.cpp"
>
</File>
<File
RelativePath=".\SpaceWarServer.cpp"
>
</File>
<File
RelativePath=".\StarField.cpp"
>
</File>
<File
RelativePath=".\StatsAndAchievements.cpp"
>
</File>
<File
RelativePath=".\Sun.cpp"
>
</File>
</Filter>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\stdafx.h"
>
</File>
<Filter
Name="Engine"
>
<File
RelativePath=".\GameEngine.h"
>
</File>
<File
RelativePath=".\VectorEntity.h"
>
</File>
</Filter>
<Filter
Name="Game"
>
<File
RelativePath=".\BaseMenu.h"
>
</File>
<File
RelativePath=".\Lobby.h"
>
</File>
<File
RelativePath=".\MainMenu.h"
>
</File>
<File
RelativePath=".\Messages.h"
>
</File>
<File
RelativePath=".\PhotonBeam.h"
>
</File>
<File
RelativePath=".\QuitMenu.h"
>
</File>
<File
RelativePath=".\ServerBrowser.h"
>
</File>
<File
RelativePath=".\ServerBrowserMenu.h"
>
</File>
<File
RelativePath=".\Ship.h"
>
</File>
<File
RelativePath=".\SpaceWar.h"
>
</File>
<File
RelativePath=".\SpaceWarClient.h"
>
</File>
<File
RelativePath=".\SpaceWarEntity.h"
>
</File>
<File
RelativePath=".\SpaceWarServer.h"
>
</File>
<File
RelativePath=".\StarField.h"
>
</File>
<File
RelativePath=".\StatsAndAchievements.h"
>
</File>
<File
RelativePath=".\Sun.h"
>
</File>
</Filter>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
+42
View File
@@ -0,0 +1,42 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for rendering the sun
//
// $NoKeywords: $
//=============================================================================
#include "stdafx.h"
#include "Sun.h"
#include <math.h>
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CSun::CSun( CGameEngine *pGameEngine ) : CSpaceWarEntity( pGameEngine, 2*SUN_VECTOR_SCALE_FACTOR, false )
{
float xcenter = (float)pGameEngine->GetViewportWidth()/2;
float ycenter = (float)pGameEngine->GetViewportHeight()/2;
float sqrtof2 = (float)sqrt( 2.0 );
DWORD dwColor = D3DCOLOR_ARGB( 255, 255, 255, 102 );
// Initialize our geometry
AddLine( (2.0f*SUN_VECTOR_SCALE_FACTOR), 0.0f, (-2.0f*SUN_VECTOR_SCALE_FACTOR), 0.0f, dwColor );
AddLine( 0.0f, (2.0f*SUN_VECTOR_SCALE_FACTOR), 0.0f, (-2.0f*SUN_VECTOR_SCALE_FACTOR), dwColor );
AddLine( -1.0f*sqrtof2*SUN_VECTOR_SCALE_FACTOR, sqrtof2*SUN_VECTOR_SCALE_FACTOR, sqrtof2*SUN_VECTOR_SCALE_FACTOR, -1.0f*sqrtof2*SUN_VECTOR_SCALE_FACTOR, dwColor );
AddLine( sqrtof2*SUN_VECTOR_SCALE_FACTOR, sqrtof2*SUN_VECTOR_SCALE_FACTOR, -1.0f*sqrtof2*SUN_VECTOR_SCALE_FACTOR, -1.0f*sqrtof2*SUN_VECTOR_SCALE_FACTOR, dwColor );
// Has to be after unlock since the base class will lock in this call
SetPosition( xcenter, ycenter );
}
//-----------------------------------------------------------------------------
// Purpose: Run a frame for the sun
//-----------------------------------------------------------------------------
void CSun::RunFrame()
{
// We want to rotate 90 degrees every 800ms (1.57 is 1/2pi, or 90 degrees in radians)
SetRotationDeltaNextFrame( (PI_VALUE/2.0f) * (float)m_pGameEngine->GetGameTicksFrameDelta()/800.0f );
CVectorEntity::RunFrame();
}
+27
View File
@@ -0,0 +1,27 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Class for rendering the sun
//
// $NoKeywords: $
//=============================================================================
#ifndef SUN_H
#define SUN_H
#include "GameEngine.h"
#include "SpaceWarEntity.h"
#define SUN_VECTOR_SCALE_FACTOR 14
class CSun : public CSpaceWarEntity
{
public:
// Constructor
CSun( CGameEngine *pGameEngine );
// Run a frame
void RunFrame();
};
#endif // SUN_H
+247
View File
@@ -0,0 +1,247 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Base class for representation objects in the game which are drawn as
// vector art (ie, a series of lines)
//
// $NoKeywords: $
//=============================================================================
#include "stdafx.h"
#include "VectorEntity.h"
#include "stdlib.h"
#include <math.h>
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CVectorEntity::CVectorEntity( CGameEngine *pGameEngine, uint32 uCollisionRadius )
{
m_uCollisionRadius = uCollisionRadius;
m_pGameEngine = pGameEngine;
m_flRotationDeltaNextFrame = 0.0;
m_flAccumulatedRotation = 0.0;
m_flXAccel = 0.0;
m_flYAccel = 0.0;
m_flXAccelLastFrame = 0.0;
m_flYAccelLastFrame = 0.0;
m_flXPos = 0.0;
m_flYPos = 0.0;
m_flXVelocity = 0.0;
m_flYVelocity = 0.0;
m_bDisableCollisions = false;
m_flRotationDeltaLastFrame = 0.0;
// we should have at least one frame Run before
// anyone asks for a delta, so this shouldn't cause
// a large initial delta to our starting position, in theory
m_flXPosLastFrame = 0;
m_flYPosLastFrame = 0;
m_flMaximumVelocity = DEFAULT_MAXIMUM_VELOCITY;
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CVectorEntity::~CVectorEntity()
{
}
//-----------------------------------------------------------------------------
// Purpose: Add a line to our geometry
//-----------------------------------------------------------------------------
void CVectorEntity::AddLine( float xPos0, float yPos0, float xPos1, float yPos1, DWORD dwColor )
{
VectorEntityVertex_t vert;
vert.x = xPos0;
vert.y = yPos0;
vert.color = dwColor;
m_VecVertexes.push_back( vert );
vert.x = xPos1;
vert.y = yPos1;
vert.color = dwColor;
m_VecVertexes.push_back( vert );
}
//-----------------------------------------------------------------------------
// Purpose: Set the current position for the object
//-----------------------------------------------------------------------------
void CVectorEntity::SetPosition( float xPos, float yPos )
{
m_flXPos = xPos;
m_flYPos = yPos;
}
//-----------------------------------------------------------------------------
// Purpose: Set the rotation to be applied next frame (in radians)
//-----------------------------------------------------------------------------
void CVectorEntity::SetRotationDeltaNextFrame( float flRotationInRadians )
{
m_flRotationDeltaNextFrame = flRotationInRadians;
}
//-----------------------------------------------------------------------------
// Purpose: Set the acceleration to be applied next frame
//-----------------------------------------------------------------------------
void CVectorEntity::SetAcceleration( float flXAccel, float flYAccel )
{
m_flXAccel = flXAccel;
m_flYAccel = flYAccel;
}
//-----------------------------------------------------------------------------
// Purpose: Run a frame for the vector entity (ie, compute rotation, position, etc...)
//-----------------------------------------------------------------------------
void CVectorEntity::RunFrame()
{
// Accumulate the rotation so we know our current rotation total at all times
m_flAccumulatedRotation += m_flRotationDeltaNextFrame;
m_flRotationDeltaLastFrame = m_flRotationDeltaNextFrame;
m_flRotationDeltaNextFrame = 0.0f;
m_flXPosLastFrame = m_flXPos;
m_flYPosLastFrame = m_flYPos;
// If the accumulated rotation is > 2pi (360) then wrap it (same for negative direction)
// This prevents the value getting really large and losing precision
int nInfiniteLoopProtector = 0;
while ( m_flAccumulatedRotation >= 2.0f*PI_VALUE && ++nInfiniteLoopProtector < 100 )
m_flAccumulatedRotation -= 2.0f*PI_VALUE;
nInfiniteLoopProtector = 0;
while ( m_flAccumulatedRotation <= -2.0f*PI_VALUE && ++nInfiniteLoopProtector < 100 )
m_flAccumulatedRotation += 2.0f*PI_VALUE;
// Update our acceleration, velocity, and finally position
// Note: The min here is so we don't get massive acceleration if frames for some reason don't run for a bit
float ulElapsedSeconds = min( (float)m_pGameEngine->GetGameTicksFrameDelta() / 1000.0f, 2 );
m_flXVelocity += m_flXAccel * ulElapsedSeconds;
m_flYVelocity += m_flYAccel * ulElapsedSeconds;
// Make sure velocity does not exceed maximum allowed
if ( m_flXVelocity > 0 && m_flXVelocity > m_flMaximumVelocity )
m_flXVelocity = m_flMaximumVelocity;
else if ( m_flXVelocity < 0 && m_flYVelocity < -1.0f*m_flMaximumVelocity )
m_flXVelocity = -1.0f * m_flMaximumVelocity;
if ( m_flYVelocity > 0 && m_flYVelocity > m_flMaximumVelocity )
m_flYVelocity = m_flMaximumVelocity;
else if ( m_flYVelocity < 0 && m_flYVelocity < -1.0f*m_flMaximumVelocity )
m_flYVelocity = -1.0f * m_flMaximumVelocity;
m_flXPos += m_flXVelocity * ulElapsedSeconds;
m_flYPos += m_flYVelocity * ulElapsedSeconds;
// Clear acceleration values, child classes should keep reseting it as appropriate each frame
m_flXAccelLastFrame = m_flXAccel;
m_flYAccelLastFrame = m_flYAccel;
m_flXAccel = 0;
m_flYAccel = 0;
// Check for wrapping around the screen
float width = (float)m_pGameEngine->GetViewportWidth();
float height = (float)m_pGameEngine->GetViewportHeight();
if ( m_flXPos > width )
m_flXPos -= width;
if ( m_flXPos < 0 )
m_flXPos += width;
if ( m_flYPos > height )
m_flYPos -= height;
if ( m_flYPos < 0 )
m_flYPos += height;
}
//-----------------------------------------------------------------------------
// Purpose: Render the entity
//-----------------------------------------------------------------------------
void CVectorEntity::Render()
{
// Compute values which will be used for rotation below
float flSinRotation = (float)sin(m_flAccumulatedRotation);
float flCosRotation = (float)cos(m_flAccumulatedRotation);
// Iterate our vector of vertexes 2 at a time drawing lines
for( size_t i=0; i < m_VecVertexes.size() - 1; ++i )
{
DWORD dwColor0, dwColor1;
float xPos0, yPos0, xPos1, yPos1;
float xPrime0, yPrime0, xPrime1, yPrime1;
// Grab the first point and apply rotation and translation
xPos0 = m_VecVertexes[i].x;
yPos0 = m_VecVertexes[i].y;
dwColor0 = m_VecVertexes[i].color;
// Apply any needed rotation
xPrime0 = flCosRotation*xPos0 - flSinRotation*yPos0;
yPrime0 = flSinRotation*xPos0 + flCosRotation*yPos0;
// Apply translation to current position
xPrime0 += m_flXPos;
yPrime0 += m_flYPos;
// Next vertex, we use 2 per iteration
++i;
// Grab the second point and apply rotation and translation
xPos1 = m_VecVertexes[i].x;
yPos1 = m_VecVertexes[i].y;
dwColor1 = m_VecVertexes[i].color;
// Apply any needed rotation
xPrime1 = flCosRotation*xPos1 - flSinRotation*yPos1;
yPrime1 = flSinRotation*xPos1 + flCosRotation*yPos1;
// Apply translation to current position
xPrime1 += m_flXPos;
yPrime1 += m_flYPos;
// Have the game engine draw the actual line (it batches these operations)
m_pGameEngine->BDrawLine( xPrime0, yPrime0, dwColor0, xPrime1, yPrime1, dwColor1 );
}
}
//-----------------------------------------------------------------------------
// Purpose: Check if the entity is colliding with the other given entity
//-----------------------------------------------------------------------------
bool CVectorEntity::BCollidesWith ( CVectorEntity * pTarget )
{
// Note: Yes, this is a lame way to do collision detection just using a set radius.
// I don't care for the moment, just want it running!
if ( m_bDisableCollisions )
return false;
else if ( pTarget->BCollisionDetectionDisabled() )
return false;
// Compute distance between the center of the two objects
float distance = (float)sqrt( pow( m_flXPos - pTarget->GetXPos(), 2 ) + pow( m_flYPos - pTarget->GetYPos(), 2 ) );
if ( distance < m_uCollisionRadius + pTarget->GetCollisionRadius() )
return true;
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Check if the entity is colliding with the other given entity
//-----------------------------------------------------------------------------
float CVectorEntity::GetDistanceTraveledLastFrame()
{
return (float)sqrt( pow( m_flXPos - m_flXPosLastFrame, 2 ) + pow( m_flYPos - m_flYPosLastFrame, 2 ) );
}
+153
View File
@@ -0,0 +1,153 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose: Base class for representation objects in the game which are drawn as
// vector art (ie, a series of lines)
//
// $NoKeywords: $
//=============================================================================
#ifndef VECTORENTITY_H
#define VECTORENTITY_H
#include "GameEngine.h"
#include <vector>
struct VectorEntityVertex_t
{
float x, y;
DWORD color;
};
#define DEFAULT_MAXIMUM_VELOCITY 350.0f
#define PI_VALUE 3.14159265f
class CVectorEntity
{
public:
// Constructor
CVectorEntity( CGameEngine *pGameEngine, uint32 uCollisionRadius );
// Destructor
virtual ~CVectorEntity();
// Run a frame
virtual void RunFrame();
// Render the sun field
virtual void Render();
// Check if the entity is colliding with another given entity
bool BCollidesWith( CVectorEntity * pTarget );
// Get the rotation value that is to be applied next frame
float GetRotationDeltaNextFrame() { return m_flRotationDeltaNextFrame; }
// Get the rotation value that was applied last frame
float GetRotationDeltaLastFrame() { return m_flRotationDeltaLastFrame; }
// Get the cumulative rotation for this entity
float GetAccumulatedRotation() { return m_flAccumulatedRotation; }
// Get the acceleration to be applied next frame
float GetXAcceleration() { return m_flXAccel; }
float GetYAcceleration() { return m_flYAccel; }
// Get the acceleration applied last frame
float GetXAccelerationLastFrame() { return m_flXAccelLastFrame; }
float GetYAccelerationLastFrame() { return m_flYAccelLastFrame; }
// Get the current velocity
float GetXVelocity() { return m_flXVelocity; }
float GetYVelocity() { return m_flYVelocity; }
// Get the current position of the object
float GetXPos() { return m_flXPos; }
float GetYPos() { return m_flYPos; }
// Get the distance traveled each frame
float GetDistanceTraveledLastFrame();
protected:
// Add a line to the entity
void AddLine( float xPos0, float yPos0, float xPos1, float yPos1, DWORD dwColor );
// Set the objects current position
void SetPosition( float xPos, float yPos );
// Set the rotation to be applied next frame
void SetRotationDeltaNextFrame( float flRotationInRadians );
// Set the acceleration to be applied next frame
void SetAcceleration( float xAccel, float yAccel );
// Set the cumulative rotation for this entity (overriding any existing value)
void SetAccumulatedRotation( float flRotation ) { m_flAccumulatedRotation = flRotation; }
// Set the velocity of the entity (normally you should just set acceleration and this will be computed)
void SetVelocity ( float xVelocity, float yVelocity ) { m_flXVelocity = xVelocity; m_flYVelocity = yVelocity; }
// Reset velocity of the entity
void ResetVelocity() { m_flXVelocity = 0; m_flYVelocity = 0; }
// Get the collision radius for the entity
uint32 GetCollisionRadius() { return m_uCollisionRadius; }
// Enable/Disable collision detection for this entity
void SetCollisionDetectionDisabled( bool bDisabled ) { m_bDisableCollisions = bDisabled; }
// Check whether collision detection has been disabled for the entity
bool BCollisionDetectionDisabled() { return m_bDisableCollisions; }
// Set a maximum velocity other than the default
void SetMaximumVelocity( float flMaximumVelocity ) { m_flMaximumVelocity = flMaximumVelocity; }
protected:
// Game engine instance we are running under
CGameEngine *m_pGameEngine;
private:
// Vector of points (always built 2 at a time so it's actually lines)
std::vector< VectorEntityVertex_t > m_VecVertexes;
// Previous position
float m_flXPosLastFrame;
float m_flYPosLastFrame;
// current position (position is at the center of the object)
float m_flXPos;
float m_flYPos;
// maximum velocity the object can have in either x/y
float m_flMaximumVelocity;
// acceleration to be applied next frame
float m_flXAccel;
float m_flYAccel;
// acceleration applied last frame
float m_flXAccelLastFrame;
float m_flYAccelLastFrame;
// current velocity (affected by acceleration changes)
float m_flXVelocity;
float m_flYVelocity;
// rotation to apply this frame (in radians)
float m_flRotationDeltaNextFrame;
// rotation which was applied last frame
float m_flRotationDeltaLastFrame;
// total cumulative rotation that has been applied to this entity
float m_flAccumulatedRotation;
// radius to use for collisions, this is applied from the center of the object out
uint32 m_uCollisionRadius;
// bool to disable collision detection for this object
bool m_bDisableCollisions;
};
#endif // VECTORENTITY_H
+18
View File
@@ -0,0 +1,18 @@
//========= Copyright © 1996-2008 Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
// stdafx.cpp : source file that includes just the standard includes
// SteamworksExample.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
#include <varargs.h>
#include <stdio.h>
#include <tchar.h>
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file
+62
View File
@@ -0,0 +1,62 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER // Allow use of features specific to Windows 2k or later.
#define WINVER 0x0500 // Change this to the appropriate value to target other versions of Windows.
#endif
#ifndef _WIN32_WINNT // Allow use of features specific to Windows 2k or later.
#define _WIN32_WINNT 0x0500 // Change this to the appropriate value to target other versions of Windows.
#endif
#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif
#ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
#define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
#endif
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#pragma comment( lib, "d3d9.lib" )
#pragma comment( lib, "d3dx9.lib" )
#pragma comment( lib, "dxguid.lib" )
// Windows Header Files:
#include <windows.h>
#include <tchar.h>
// Winsock
#include <winsock.h>
#pragma comment(lib, "ws2_32.lib" )
// d3d header files
#include "d3d9.h"
#include "d3dx9.h"
typedef __int16 int16;
typedef unsigned __int16 uint16;
typedef __int32 int32;
typedef unsigned __int32 uint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
// steam api header file
#include "steam/steam_api.h"
+1
View File
@@ -0,0 +1 @@
480
+26
View File
@@ -0,0 +1,26 @@
#
# *********** (C) Copyright 2008 Valve, L.L.C. All rights reserved. ***********
#
# Steam Client SDK configuration-override file
#
# This file is read by the Steam engine. This file should be located
# in the same folder as steam.exe
#
#
# Use this value to specify the dot-notation IP address or hostname
# of the Steam Content Server for development/test.
# Use "127.0.0.1" to specify the primary NIC of current host.
#
# If you need to run multiple content servers, you can specify
# multiple addresses on this line seperated by a space character
# (e.g. "11.22.33.44 11.22.33.45")
#
SdkContentServerAdrs = "127.0.0.1"
#
# Enable the manifest fingerprint check at cache startup.
# In general, this should always be enabled if your client is connecting
# to an SDK content server.
#
ManifestFingerprintCheck = enable
BIN
View File
Binary file not shown.
+40
View File
@@ -0,0 +1,40 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose: interface to app data in Steam
//
//=============================================================================
#ifndef ISTEAMAPPS_H
#define ISTEAMAPPS_H
#ifdef _WIN32
#pragma once
#endif
#include "steam/isteamapps.h"
//-----------------------------------------------------------------------------
// Purpose: interface to app data
//-----------------------------------------------------------------------------
class ISteamApps
{
public:
// returns 0 if the key does not exist
// this may be true on first call, since the app data may not be cached locally yet
// If you expect it to exists wait for the AppDataChanged_t after the first failure and ask again
virtual int GetAppData( AppId_t nAppID, const char *pchKey, char *pchValue, int cchValueMax ) = 0;
};
#define STEAMAPPS_INTERFACE_VERSION "STEAMAPPS_INTERFACE_VERSION001"
//-----------------------------------------------------------------------------
// Purpose: called when new information about an app has arrived
//-----------------------------------------------------------------------------
struct AppDataChanged_t
{
enum { k_iCallback = k_iSteamAppsCallbacks + 1 };
uint32 m_nAppID; // appid that changed
bool m_bBySteamUI; // change came from SteamUI
bool m_bCDDBUpdate; // the cddb entry for this app changed
};
#endif // ISTEAMAPPS_H
+142
View File
@@ -0,0 +1,142 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose: Main interface for loading and accessing Steamworks API's from the
// Steam client.
// For most uses, this code is wrapped inside of SteamAPI_Init()
//=============================================================================
#ifndef ISTEAMCLIENT_H
#define ISTEAMCLIENT_H
#ifdef _WIN32
#pragma once
#endif
#include "steamtypes.h"
#include "steamclientpublic.h"
// handle to a communication pipe to the Steam client
typedef int32 HSteamPipe;
// handle to single instance of a steam user
typedef int32 HSteamUser;
// function prototype
extern "C" typedef void (__cdecl *SteamAPIWarningMessageHook_t)(int, const char *);
// interface predec
class ISteamUser;
class ISteamGameServer;
class ISteamFriends;
class ISteamUtils;
class ISteamMatchmaking;
class ISteamContentServer;
class ISteamMasterServerUpdater;
class ISteamMatchmakingServers;
class ISteamUserStats;
class ISteamApps;
class ISteamNetworking;
//-----------------------------------------------------------------------------
// Purpose: Interface to creating a new steam instance, or to
// connect to an existing steam instance, whether it's in a
// different process or is local.
//
// For most scenarios this is all handled automatically via SteamAPI_Init().
// You'll only need to use these interfaces if you have a more complex versioning scheme,
// where you want to get different versions of the same interface in different dll's in your project.
//-----------------------------------------------------------------------------
class ISteamClient
{
public:
// Creates a communication pipe to the Steam client
virtual HSteamPipe CreateSteamPipe() = 0;
// Releases a previously created communications pipe
virtual bool BReleaseSteamPipe( HSteamPipe hSteamPipe ) = 0;
// connects to an existing global user, failing if none exists
// used by the game to coordinate with the steamUI
virtual HSteamUser ConnectToGlobalUser( HSteamPipe hSteamPipe ) = 0;
// used by game servers, create a steam user that won't be shared with anyone else
virtual HSteamUser CreateLocalUser( HSteamPipe *phSteamPipe ) = 0;
// removes an allocated user
virtual void ReleaseUser( HSteamPipe hSteamPipe, HSteamUser hUser ) = 0;
// retrieves the ISteamUser interface associated with the handle
virtual ISteamUser *GetISteamUser( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0;
// retrieves the ISteamGameServer interface associated with the handle
virtual ISteamGameServer *GetISteamGameServer( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0;
// set the local IP and Port to bind to
// this must be set before CreateLocalUser()
virtual void SetLocalIPBinding( uint32 unIP, uint16 usPort ) = 0;
// returns the ISteamFriends interface
virtual ISteamFriends *GetISteamFriends( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0;
// returns the ISteamUtils interface
virtual ISteamUtils *GetISteamUtils( HSteamPipe hSteamPipe, const char *pchVersion ) = 0;
// returns the ISteamMatchmaking interface
virtual ISteamMatchmaking *GetISteamMatchmaking( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0;
// returns the ISteamContentServer interface
virtual ISteamContentServer *GetISteamContentServer( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0;
// returns the ISteamMasterServerUpdater interface
virtual ISteamMasterServerUpdater *GetISteamMasterServerUpdater( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0;
// returns the ISteamMatchmakingServers interface
virtual ISteamMatchmakingServers *GetISteamMatchmakingServers( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0;
// returns the a generic interface
virtual void *GetISteamGenericInterface( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0;
// this needs to be called every frame to process matchmaking results
// redundant if you're already calling SteamAPI_RunCallbacks()
virtual void RunFrame() = 0;
// returns the number of IPC calls made since the last time this function was called
// Used for perf debugging so you can understand how many IPC calls your game makes per frame
// Every IPC call is at minimum a thread context switch if not a process one so you want to rate
// control how often you do them.
virtual uint32 GetIPCCallCount() = 0;
// returns the ISteamUserStats interface
virtual ISteamUserStats *GetISteamUserStats( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0;
// returns apps interface
virtual ISteamApps *GetISteamApps( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0;
// networking
virtual ISteamNetworking *GetISteamNetworking( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion ) = 0;
// API warning handling
// 'int' is the severity; 0 for msg, 1 for warning
// 'const char *' is the text of the message
// callbacks will occur directly after the API function is called that generated the warning or message
virtual void SetWarningMessageHook( SteamAPIWarningMessageHook_t pFunction ) = 0;
};
#define STEAMCLIENT_INTERFACE_VERSION "SteamClient007"
//-----------------------------------------------------------------------------
// Purpose: Base values for callback identifiers, each callback must
// have a unique ID.
//-----------------------------------------------------------------------------
enum { k_iSteamUserCallbacks = 100 };
enum { k_iSteamGameServerCallbacks = 200 };
enum { k_iSteamFriendsCallbacks = 300 };
enum { k_iSteamBillingCallbacks = 400 };
enum { k_iSteamMatchmakingCallbacks = 500 };
enum { k_iSteamContentServerCallbacks = 600 };
enum { k_iSteamUtilsCallbacks = 700 };
enum { k_iClientFriendsCallbacks = 800 };
enum { k_iClientUserCallbacks = 900 };
enum { k_iSteamAppsCallbacks = 1000 };
enum { k_iSteamUserStatsCallbacks = 1100 };
enum { k_iSteamNetworkingCallbacks = 1200 };
#endif // ISTEAMCLIENT_H
+200
View File
@@ -0,0 +1,200 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose: interface to both friends list data and general information about users
//
//=============================================================================
#ifndef ISTEAMFRIENDS_H
#define ISTEAMFRIENDS_H
#ifdef _WIN32
#pragma once
#endif
#include "isteamclient.h"
//-----------------------------------------------------------------------------
// Purpose: set of relationships to other users
//-----------------------------------------------------------------------------
enum EFriendRelationship
{
k_EFriendRelationshipNone = 0,
k_EFriendRelationshipBlocked = 1,
k_EFriendRelationshipRequestRecipient = 2,
k_EFriendRelationshipFriend = 3,
k_EFriendRelationshipRequestInitiator = 4,
k_EFriendRelationshipIgnored = 5,
k_EFriendRelationshipIgnoredFriend = 6,
};
//-----------------------------------------------------------------------------
// Purpose: list of states a friend can be in
//-----------------------------------------------------------------------------
enum EPersonaState
{
k_EPersonaStateOffline = 0, // friend is not currently logged on
k_EPersonaStateOnline = 1, // friend is logged on
k_EPersonaStateBusy = 2, // user is on, but busy
k_EPersonaStateAway = 3, // auto-away feature
k_EPersonaStateSnooze = 4, // auto-away for a long time
k_EPersonaStateMax,
};
//-----------------------------------------------------------------------------
// Purpose: flags for enumerating friends list, or quickly checking a the relationship between users
//-----------------------------------------------------------------------------
enum k_EFriendFlags
{
k_EFriendFlagNone = 0x00,
k_EFriendFlagBlocked = 0x01,
k_EFriendFlagFriendshipRequested = 0x02,
k_EFriendFlagImmediate = 0x04, // "regular" friend
k_EFriendFlagClanMember = 0x08,
k_EFriendFlagOnGameServer = 0x10,
// k_EFriendFlagHasPlayedWith = 0x20, // not currently used
// k_EFriendFlagFriendOfFriend = 0x40, // not currently used
k_EFriendFlagRequestingFriendship = 0x80,
k_EFriendFlagRequestingInfo = 0x100,
k_EFriendFlagIgnored = 0x200,
k_EFriendFlagIgnoredFriend = 0x400,
k_EFriendFlagAll = 0xFFFF,
};
// maximum number of characters in a users name
enum { k_cchPersonaNameMax = 128 };
// size limit on chat room or member metadata
const uint32 k_cubChatMetadataMax = 4096;
//-----------------------------------------------------------------------------
// Purpose: interface to accessing information about individual users,
// that can be a friend, in a group, on a game server or in a lobby with the local user
//-----------------------------------------------------------------------------
class ISteamFriends
{
public:
// returns the local players name - guaranteed to not be NULL.
// this is the same name as on the users community profile page
// this is stored in UTF-8 format
// like all the other interface functions that return a char *, it's important that this pointer is not saved
// off; it will eventually be free'd or re-allocated
virtual const char *GetPersonaName() = 0;
// sets the player name, stores it on the server and publishes the changes to all friends who are online
virtual void SetPersonaName( const char *pchPersonaName ) = 0;
// gets the status of the current user
virtual EPersonaState GetPersonaState() = 0;
// friend iteration
// takes a set of k_EFriendFlags, and returns the number of users the client knows about who meet that criteria
// then GetFriendByIndex() can then be used to return the id's of each of those users
virtual int GetFriendCount( int iFriendFlags ) = 0;
// returns the steamID of a user
// iFriend is a index of range [0, GetFriendCount())
// iFriendsFlags must be the same value as used in GetFriendCount()
// the returned CSteamID can then be used by all the functions below to access details about the user
virtual CSteamID GetFriendByIndex( int iFriend, int iFriendFlags ) = 0;
// returns a relationship to a user
virtual EFriendRelationship GetFriendRelationship( CSteamID steamIDFriend ) = 0;
// returns the current status of the specified user
// this will only be known by the local user if steamIDFriend is in their friends list; on the same game server; in a chat room or lobby; or in a small group with the local user
virtual EPersonaState GetFriendPersonaState( CSteamID steamIDFriend ) = 0;
// returns the name another user - guaranteed to not be NULL.
// same rules as GetFriendPersonaState() apply as to whether or not the user knowns the name of the other user
// note that on first joining a lobby, chat room or game server the local user will not known the name of the other users automatically; that information will arrive asyncronously
//
virtual const char *GetFriendPersonaName( CSteamID steamIDFriend ) = 0;
// gets the avatar of the current user, which is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set
virtual int GetFriendAvatar( CSteamID steamIDFriend ) = 0;
// returns true if the friend is actually in a game
virtual bool GetFriendGamePlayed( CSteamID steamIDFriend, uint64 *pulGameID, uint32 *punGameIP, uint16 *pusGamePort, uint16 *pusQueryPort ) = 0;
// accesses old friends names - returns an empty string when their are no more items in the history
virtual const char *GetFriendPersonaNameHistory( CSteamID steamIDFriend, int iPersonaName ) = 0;
// returns true if the specified user meets any of the criteria specified in iFriendFlags
// iFriendFlags can be the union (binary or, |) of one or more k_EFriendFlags values
virtual bool HasFriend( CSteamID steamIDFriend, int iFriendFlags ) = 0;
// clan (group) iteration and access functions
virtual int GetClanCount() = 0;
virtual CSteamID GetClanByIndex( int iClan ) = 0;
virtual const char *GetClanName( CSteamID steamIDClan ) = 0;
// iterators for getting users in a chat room, lobby, game server or clan
// note that large clans that cannot be iterated by the local user
// steamIDSource can be the steamID of a group, game server, lobby or chat room
virtual int GetFriendCountFromSource( CSteamID steamIDSource ) = 0;
virtual CSteamID GetFriendFromSourceByIndex( CSteamID steamIDSource, int iFriend ) = 0;
// returns true if the local user can see that steamIDUser is a member or in steamIDSource
virtual bool IsUserInSource( CSteamID steamIDUser, CSteamID steamIDSource ) = 0;
// User is in a game pressing the talk button (will suppress the microphone for all voice comms from the Steam friends UI)
virtual void SetInGameVoiceSpeaking( CSteamID steamIDUser, bool bSpeaking ) = 0;
// activates the game overlay, with an optional dialog to open ("Friends", "Community", "Players", "Settings")
virtual void ActivateGameOverlay( const char *pchDialog ) = 0;
};
#define STEAMFRIENDS_INTERFACE_VERSION "SteamFriends003"
//-----------------------------------------------------------------------------
// Purpose: called when a friends' status changes
//-----------------------------------------------------------------------------
struct PersonaStateChange_t
{
enum { k_iCallback = k_iSteamFriendsCallbacks + 4 };
uint64 m_ulSteamID; // steamID of the friend who changed
int m_nChangeFlags; // what's changed
};
// used in PersonaStateChange_t::m_nChangeFlags to describe what's changed about a user
// these flags describe what the client has learned has changed recently, so on startup you'll see a name, avatar & relationship change for every friend
enum EPersonaChange
{
k_EPersonaChangeName = 0x001,
k_EPersonaChangeStatus = 0x002,
k_EPersonaChangeComeOnline = 0x004,
k_EPersonaChangeGoneOffline = 0x008,
k_EPersonaChangeGamePlayed = 0x010,
k_EPersonaChangeGameServer = 0x020,
k_EPersonaChangeAvatar = 0x040,
k_EPersonaChangeJoinedSource= 0x080,
k_EPersonaChangeLeftSource = 0x100,
k_EPersonaChangeRelationshipChanged = 0x200,
k_EPersonaChangeNameFirstSet = 0x400,
};
//-----------------------------------------------------------------------------
// Purpose: posted when game overlay activates or deactivates
// the game can use this to be pause or resume single player games
//-----------------------------------------------------------------------------
struct GameOverlayActivated_t
{
enum { k_iCallback = k_iSteamFriendsCallbacks + 31 };
uint8 m_bActive; // true if it's just been activated, false otherwise
};
//-----------------------------------------------------------------------------
// Purpose: called when the user tries to join a different game server from their friends list
// game client should attempt to connect to specified server when this is received
//-----------------------------------------------------------------------------
struct GameServerChangeRequested_t
{
enum { k_iCallback = k_iSteamFriendsCallbacks + 32 };
char m_rgchServer[64]; // server address ("127.0.0.1:27015", "tf2.valvesoftware.com")
char m_rgchPassword[64]; // server password, if any
};
#endif // ISTEAMFRIENDS_H
+160
View File
@@ -0,0 +1,160 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose: interface to steam for game servers
//
//=============================================================================
#ifndef ISTEAMGAMESERVER_H
#define ISTEAMGAMESERVER_H
#ifdef _WIN32
#pragma once
#endif
#include "isteamclient.h"
//-----------------------------------------------------------------------------
// Purpose: Functions for authenticating users via Steam to play on a game server
//-----------------------------------------------------------------------------
class ISteamGameServer
{
public:
// connection functions
virtual void LogOn() = 0;
virtual void LogOff() = 0;
// status functions
virtual bool BLoggedOn() = 0;
virtual bool BSecure() = 0;
virtual CSteamID GetSteamID() = 0;
// Handles receiving a new connection from a Steam user. This call will ask the Steam
// servers to validate the users identity, app ownership, and VAC status. If the Steam servers
// are off-line, then it will validate the cached ticket itself which will validate app ownership
// and identity. The AuthBlob here should be acquired on the game client using SteamUser()->InitiateGameConnection()
// and must then be sent up to the game server for authentication.
//
// Return Value: true/false depending on whether the call succeeds. If the call succeeds then you
// should expect a GSClientApprove_t or GSClientDeny_t callback which will tell you whether authentication
// for the user has succeeded or failed.
virtual void SendUserConnectAndAuthenticate( CSteamID steamIDUser, uint32 unIPClient, void *pvAuthBlob, uint32 cubAuthBlobSize ) = 0;
// Creates a fake user (ie, a bot) which will be listed as playing on the server, but skips validation.
//
// Return Value: Returns a SteamID for the user to be tracked with, you should call HandleUserDisconnect()
// when this user leaves the server just like you would for a real user.
virtual CSteamID CreateUnauthenticatedUserConnection() = 0;
// Should be called whenever a user leaves our game server, this lets Steam internally
// track which users are currently on which servers for the purposes of preventing a single
// account being logged into multiple servers, showing who is currently on a server, etc.
virtual void SendUserDisconnect( CSteamID steamIDUser ) = 0;
// Update the data to be displayed in the server browser and matchmaking interfaces for a user
// currently connected to the server. For regular users you must call this after you receive a
// GSUserValidationSuccess callback.
//
// Return Value: true if successful, false if failure (ie, steamIDUser wasn't for an active player)
virtual bool BUpdateUserData( CSteamID steamIDUser, const char *pchPlayerName, uint32 uScore ) = 0;
// You shouldn't need to call this as it is called internally by SteamGameServer_Init() and can only be called once.
//
// To update the data in this call which may change during the servers lifetime see UpdateServerStatus() below.
//
// Input: nGameAppID - The Steam assigned AppID for the game
// unServerFlags - Any applicable combination of flags (see k_unServerFlag____ constants below)
// unGameIP - The IP Address the server is listening for client connections on (might be INADDR_ANY)
// unGamePort - The port which the server is listening for client connections on
// unSpectatorPort - the port on which spectators can join to observe the server, 0 if spectating is not supported
// usQueryPort - The port which the ISteamMasterServerUpdater API should use in order to listen for matchmaking requests
// pchGameDir - A unique string identifier for your game
// pchVersion - The current version of the server as a string like 1.0.0.0
// bLanMode - Is this a LAN only server?
//
// bugbug jmccaskey - figure out how to remove this from the API and only expose via SteamGameServer_Init... or make this actually used,
// and stop calling it in SteamGameServer_Init()?
virtual bool BSetServerType( int32 nGameAppId, uint32 unServerFlags, uint32 unGameIP, uint16 unGamePort,
uint16 unSpectatorPort, uint16 usQueryPort, const char *pchGameDir, const char *pchVersion, bool bLANMode ) = 0;
// Updates server status values which shows up in the server browser and matchmaking APIs
virtual void UpdateServerStatus( int cPlayers, int cPlayersMax, int cBotPlayers,
const char *pchServerName, const char *pSpectatorServerName,
const char *pchMapName ) = 0;
// This can be called if spectator goes away or comes back (passing 0 means there is no spectator server now).
virtual void UpdateSpectatorPort( uint16 unSpectatorPort ) = 0;
// Sets a string defining the "gametype" for this server, this is optional, but if it is set
// it allows users to filter in the matchmaking/server-browser interfaces based on the value
virtual void SetGameType( const char *pchGameType ) = 0;
// Ask if a user has a specific achievement for this game, will get a callback on reply
virtual bool BGetUserAchievementStatus( CSteamID steamID, const char *pchAchievementName ) = 0;
};
#define STEAMGAMESERVER_INTERFACE_VERSION "SteamGameServer004"
// game server flags
const uint32 k_unServerFlagNone = 0x00;
const uint32 k_unServerFlagActive = 0x01; // server has users playing
const uint32 k_unServerFlagSecure = 0x02; // server wants to be secure
const uint32 k_unServerFlagDedicated = 0x04; // server is dedicated
const uint32 k_unServerFlagLinux = 0x08; // linux build
const uint32 k_unServerFlagPassworded = 0x10; // password protected
const uint32 k_unServerFlagPrivate = 0x20; // server shouldn't list on master server and
// won't enforce authentication of users that connect to the server.
// Useful when you run a server where the clients may not
// be connected to the internet but you want them to play (i.e LANs)
// callbacks
// client has been approved to connect to this game server
struct GSClientApprove_t
{
enum { k_iCallback = k_iSteamGameServerCallbacks + 1 };
CSteamID m_SteamID;
};
// client has been denied to connection to this game server
struct GSClientDeny_t
{
enum { k_iCallback = k_iSteamGameServerCallbacks + 2 };
CSteamID m_SteamID;
EDenyReason m_eDenyReason;
char m_rgchOptionalText[128];
};
// request the game server should kick the user
struct GSClientKick_t
{
enum { k_iCallback = k_iSteamGameServerCallbacks + 3 };
CSteamID m_SteamID;
EDenyReason m_eDenyReason;
};
// NOTE: callback values 4 and 5 are skipped because they are used for old deprecated callbacks,
// do not reuse them here.
// client achievement info
struct GSClientAchievementStatus_t
{
enum { k_iCallback = k_iSteamGameServerCallbacks + 6 };
uint64 m_SteamID;
char m_pchAchievement[128];
bool m_bUnlocked;
};
// received when the game server requests to be displayed as secure (VAC protected)
// m_bSecure is true if the game server should display itself as secure to users, false otherwise
struct GSPolicyResponse_t
{
enum { k_iCallback = k_iSteamUserCallbacks + 15 };
uint8 m_bSecure;
};
#endif // ISTEAMGAMESERVER_H
+103
View File
@@ -0,0 +1,103 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose: interface to steam for retrieving list of game servers
//
//=============================================================================
#ifndef ISTEAMMASTERSERVERUPDATER_H
#define ISTEAMMASTERSERVERUPDATER_H
#ifdef _WIN32
#pragma once
#endif
#include "isteamclient.h"
#define MASTERSERVERUPDATERPORT_USEGAMESOCKETSHARE ((uint16)-1)
//-----------------------------------------------------------------------------
// Purpose: Game engines use this to tell the Steam master servers
// about their games so their games can show up in the server browser.
//-----------------------------------------------------------------------------
class ISteamMasterServerUpdater
{
public:
// Call this as often as you like to tell the master server updater whether or not
// you want it to be active (default: off).
virtual void SetActive( bool bActive ) = 0;
// You usually don't need to modify this.
// Pass -1 to use the default value for iHeartbeatInterval.
// Some mods change this.
virtual void SetHeartbeatInterval( int iHeartbeatInterval ) = 0;
// These are in GameSocketShare mode, where instead of ISteamMasterServerUpdater creating its own
// socket to talk to the master server on, it lets the game use its socket to forward messages
// back and forth. This prevents us from requiring server ops to open up yet another port
// in their firewalls.
//
// the IP address and port should be in host order, i.e 127.0.0.1 == 0x7f000001
// These are used when you've elected to multiplex the game server's UDP socket
// rather than having the master server updater use its own sockets.
//
// Source games use this to simplify the job of the server admins, so they
// don't have to open up more ports on their firewalls.
// Call this when a packet that starts with 0xFFFFFFFF comes in. That means
// it's for us.
virtual bool HandleIncomingPacket( const void *pData, int cbData, uint32 srcIP, uint16 srcPort ) = 0;
// AFTER calling HandleIncomingPacket for any packets that came in that frame, call this.
// This gets a packet that the master server updater needs to send out on UDP.
// It returns the length of the packet it wants to send, or 0 if there are no more packets to send.
// Call this each frame until it returns 0.
virtual int GetNextOutgoingPacket( void *pOut, int cbMaxOut, uint32 *pNetAdr, uint16 *pPort ) = 0;
// Functions to set various fields that are used to respond to queries.
// Call this to set basic data that is passed to the server browser.
virtual void SetBasicServerData(
unsigned short nProtocolVersion,
bool bDedicatedServer,
const char *pRegionName,
const char *pProductName,
unsigned short nMaxReportedClients,
bool bPasswordProtected,
const char *pGameDescription ) = 0;
// Call this to clear the whole list of key/values that are sent in rules queries.
virtual void ClearAllKeyValues() = 0;
// Call this to add/update a key/value pair.
virtual void SetKeyValue( const char *pKey, const char *pValue ) = 0;
// You can call this upon shutdown to clear out data stored for this game server and
// to tell the master servers that this server is going away.
virtual void NotifyShutdown() = 0;
// Returns true if the master server has requested a restart.
// Only returns true once per request.
virtual bool WasRestartRequested() = 0;
// Force it to request a heartbeat from the master servers.
virtual void ForceHeartbeat() = 0;
// Manually edit and query the master server list.
// It will provide name resolution and use the default master server port if none is provided.
virtual bool AddMasterServer( const char *pServerAddress ) = 0;
virtual bool RemoveMasterServer( const char *pServerAddress ) = 0;
virtual int GetNumMasterServers() = 0;
// Returns the # of bytes written to pOut.
virtual int GetMasterServerAddress( int iServer, char *pOut, int outBufferSize ) = 0;
};
#define STEAMMASTERSERVERUPDATER_INTERFACE_VERSION "SteamMasterServerUpdater001"
#endif // ISTEAMMASTERSERVERUPDATER_H
+477
View File
@@ -0,0 +1,477 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose: interface to steam managing game server/client match making
//
//=============================================================================
#ifndef ISTEAMMATCHMAKING
#define ISTEAMMATCHMAKING
#ifdef _WIN32
#pragma once
#endif
#include "steamtypes.h"
#include "steamclientpublic.h"
#include "matchmakingtypes.h"
#include "isteamclient.h"
#include "isteamfriends.h"
//-----------------------------------------------------------------------------
// Purpose: Functions for match making services for clients to get to favorites
// and to operate on game lobbies.
//-----------------------------------------------------------------------------
class ISteamMatchmaking
{
public:
// game server favorites storage
// saves basic details about a multiplayer game server locally
// returns the number of favorites servers the user has stored
virtual int GetFavoriteGameCount() = 0;
// returns the details of the game server
// iGame is of range [0,GetFavoriteGameCount())
// *pnIP, *pnConnPort are filled in the with IP:port of the game server
// *punFlags specify whether the game server was stored as an explicit favorite or in the history of connections
// *pRTime32LastPlayedOnServer is filled in the with the Unix time the favorite was added
virtual bool GetFavoriteGame( int iGame, AppId_t *pnAppID, uint32 *pnIP, uint16 *pnConnPort, uint16 *pnQueryPort, uint32 *punFlags, uint32 *pRTime32LastPlayedOnServer ) = 0;
// adds the game server to the local list; updates the time played of the server if it already exists in the list
virtual int AddFavoriteGame( AppId_t nAppID, uint32 nIP, uint16 nConnPort, uint16 nQueryPort, uint32 unFlags, uint32 rTime32LastPlayedOnServer ) =0;
// removes the game server from the local storage; returns true if one was removed
virtual bool RemoveFavoriteGame( AppId_t nAppID, uint32 nIP, uint16 nConnPort, uint16 nQueryPort, uint32 unFlags ) = 0;
///////
// Game lobby functions
// Get a list of relevant lobbies
// this is an asynchronous request
// results will be returned by LobbyMatchList_t callback, with the number of servers requested
// if the user is not currently connected to Steam (i.e. SteamUser()->BLoggedOn() returns false) then
// a LobbyMatchList_t callback will be posted immediately with no servers
virtual void RequestLobbyList() = 0;
// returns the CSteamID of a lobby, as retrieved by a RequestLobbyList call
// should only be called after a LobbyMatchList_t callback is received
// iLobby is of the range [0, LobbyMatchList_t::m_nLobbiesMatching)
// the returned CSteamID::IsValid() will be false if iLobby is out of range
virtual CSteamID GetLobbyByIndex( int iLobby ) = 0;
// Create a lobby on the Steam servers.
// If bPrivate is true, then the lobby will not be returned by any RequestLobbyList() call; the CSteamID
// of the lobby will need to be communicated via game channels or via InviteUserToLobby()
// this is an asynchronous request
// results will be returned by LobbyCreated_t callback when the lobby has been created;
// local user will the join the lobby, resulting in an additional LobbyEnter_t callback being sent
// operations on the chat room can only proceed once the LobbyEnter_t has been received
virtual void CreateLobby( bool bPrivate ) = 0;
// Joins an existing lobby
// this is an asynchronous request
// results will be returned by LobbyEnter_t callback when the lobby has been joined
virtual void JoinLobby( CSteamID steamIDLobby ) = 0;
// Leave a lobby; this will take effect immediately on the client side
// other users in the lobby will be notified by a LobbyChatUpdate_t callback
virtual void LeaveLobby( CSteamID steamIDLobby ) = 0;
// Invite another user to the lobby
// the target user will receive a LobbyInvite_t callback
// will return true if the invite is successfully sent, whether or not the target responds
// returns false if the local user is not connected to the Steam servers
virtual bool InviteUserToLobby( CSteamID steamIDLobby, CSteamID steamIDInvitee ) = 0;
// Lobby iteration, for viewing details of users in a lobby
// only accessible if the lobby user is a member of the specified lobby
// persona information for other lobby members (name, avatar, etc.) will be asynchronously received
// and accessible via ISteamFriends interface
// returns the number of users in the specified lobby
virtual int GetNumLobbyMembers( CSteamID steamIDLobby ) = 0;
// returns the CSteamID of a user in the lobby
// iMember is of range [0,GetNumLobbyMembers())
virtual CSteamID GetLobbyMemberByIndex( CSteamID steamIDLobby, int iMember ) = 0;
// Get data associated with this lobby
// takes a simple key, and returns the string associated with it
// "" will be returned if no value is set, or if steamIDLobby is invalid
virtual const char *GetLobbyData( CSteamID steamIDLobby, const char *pchKey ) = 0;
// Sets a key/value pair in the lobby metadata
// each user in the lobby will be broadcast this new value, and any new users joining will receive any existing data
// this can be used to set lobby names, map, etc.
// to reset a key, just set it to ""
// other users in the lobby will receive notification of the lobby data change via a LobbyDataUpdate_t callback
virtual bool SetLobbyData( CSteamID steamIDLobby, const char *pchKey, const char *pchValue ) = 0;
// As above, but gets per-user data for someone in this lobby
virtual const char *GetLobbyMemberData( CSteamID steamIDLobby, CSteamID steamIDUser, const char *pchKey ) = 0;
// Sets per-user metadata (for the local user implicitly)
virtual void SetLobbyMemberData( CSteamID steamIDLobby, const char *pchKey, const char *pchValue ) = 0;
// Broadcasts a chat message to the all the users in the lobby
// users in the lobby (including the local user) will receive a LobbyChatMsg_t callback
// returns true if the message is successfully sent
virtual bool SendLobbyChatMsg( CSteamID steamIDLobby, const void *pvMsgBody, int cubMsgBody ) = 0;
// Get a chat message as specified in a LobbyChatMsg_t callback
// iChatID is the LobbyChatMsg_t::m_iChatID value in the callback
// *pSteamIDUser is filled in with the CSteamID of the member
// *pvData is filled in with the message itself
// return value is the number of bytes written into the buffer
virtual int GetLobbyChatEntry( CSteamID steamIDLobby, int iChatID, CSteamID *pSteamIDUser, void *pvData, int cubData, EChatEntryType *peChatEntryType ) = 0;
// Fetch metadata for a lobby you're not necessarily in right now
// this will send down all the metadata associated with a lobby
// this is an asynchronous call
// returns false if the local user is not connected to the Steam servers
virtual bool RequestLobbyData( CSteamID steamIDLobby ) = 0;
// sets the game server associated with the lobby
// usually at this point, the users will leave the lobby and join the specified game server
// either the IP/Port or the steamID of the game server has to be valid, depending on how you want the clients to be able to connect
virtual void SetLobbyGameServer( CSteamID steamIDLobby, uint32 unGameServerIP, uint16 unGameServerPort, CSteamID steamIDGameServer ) = 0;
};
#define STEAMMATCHMAKING_INTERFACE_VERSION "SteamMatchMaking002"
//-----------------------------------------------------------------------------
// Callback interfaces for server list functions (see ISteamMatchmakingServers below)
//
// The idea here is that your game code implements objects that implement these
// interfaces to receive callback notifications after calling asynchronous functions
// inside the ISteamMatchmakingServers() interface below.
//
// This is different than normal Steam callback handling due to the potentially
// large size of server lists.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Purpose: Callback interface for receiving responses after a server list refresh
// or an individual server update.
//
// Since you get these callbacks after requesting full list refreshes you will
// usually implement this interface inside an object like CServerBrowser. If that
// object is getting destructed you should use ISteamMatchMakingServers()->CancelQuery()
// to cancel any in-progress queries so you don't get a callback into the destructed
// object and crash.
//-----------------------------------------------------------------------------
class ISteamMatchmakingServerListResponse
{
public:
// Server has responded ok with updated data
virtual void ServerResponded( int iServer ) = 0;
// Server has failed to respond
virtual void ServerFailedToRespond( int iServer ) = 0;
// A list refresh you had initiated is now 100% completed
virtual void RefreshComplete( EMatchMakingServerResponse response ) = 0;
};
//-----------------------------------------------------------------------------
// Purpose: Callback interface for receiving responses after pinging an individual server
//
// These callbacks all occur in response to querying an individual server
// via the ISteamMatchmakingServers()->PingServer() call below. If you are
// destructing an object that implements this interface then you should call
// ISteamMatchmakingServers()->CancelServerQuery() passing in the handle to the query
// which is in progress. Failure to cancel in progress queries when destructing
// a callback handler may result in a crash when a callback later occurs.
//-----------------------------------------------------------------------------
class ISteamMatchmakingPingResponse
{
public:
// Server has responded successfully and has updated data
virtual void ServerResponded( gameserveritem_t &server ) = 0;
// Server failed to respond to the ping request
virtual void ServerFailedToRespond() = 0;
};
//-----------------------------------------------------------------------------
// Purpose: Callback interface for receiving responses after requesting details on
// who is playing on a particular server.
//
// These callbacks all occur in response to querying an individual server
// via the ISteamMatchmakingServers()->PlayerDetails() call below. If you are
// destructing an object that implements this interface then you should call
// ISteamMatchmakingServers()->CancelServerQuery() passing in the handle to the query
// which is in progress. Failure to cancel in progress queries when destructing
// a callback handler may result in a crash when a callback later occurs.
//-----------------------------------------------------------------------------
class ISteamMatchmakingPlayersResponse
{
public:
// Got data on a new player on the server -- you'll get this callback once per player
// on the server which you have requested player data on.
virtual void AddPlayerToList( const char *pchName, int nScore, float flTimePlayed ) = 0;
// The server failed to respond to the request for player details
virtual void PlayersFailedToRespond() = 0;
// The server has finished responding to the player details request
// (ie, you won't get anymore AddPlayerToList callbacks)
virtual void PlayersRefreshComplete() = 0;
};
//-----------------------------------------------------------------------------
// Purpose: Callback interface for receiving responses after requesting rules
// details on a particular server.
//
// These callbacks all occur in response to querying an individual server
// via the ISteamMatchmakingServers()->ServerRules() call below. If you are
// destructing an object that implements this interface then you should call
// ISteamMatchmakingServers()->CancelServerQuery() passing in the handle to the query
// which is in progress. Failure to cancel in progress queries when destructing
// a callback handler may result in a crash when a callback later occurs.
//-----------------------------------------------------------------------------
class ISteamMatchmakingRulesResponse
{
public:
// Got data on a rule on the server -- you'll get one of these per rule defined on
// the server you are querying
virtual void RulesResponded( const char *pchRule, const char *pchValue ) = 0;
// The server failed to respond to the request for rule details
virtual void RulesFailedToRespond() = 0;
// The server has finished responding to the rule details request
// (ie, you won't get anymore RulesResponded callbacks)
virtual void RulesRefreshComplete() = 0;
};
//-----------------------------------------------------------------------------
// Typedef for handle type you will receive when querying details on an individual server.
//-----------------------------------------------------------------------------
typedef int HServerQuery;
const int HSERVERQUERY_INVALID = 0xffffffff;
//-----------------------------------------------------------------------------
// Purpose: Functions for match making services for clients to get to game lists and details
//-----------------------------------------------------------------------------
class ISteamMatchmakingServers
{
public:
// Request a new list of servers of a particular type. These calls each correspond to one of the EMatchMakingType values.
virtual void RequestInternetServerList( AppId_t iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0;
virtual void RequestLANServerList( AppId_t iApp, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0;
virtual void RequestFriendsServerList( AppId_t iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0;
virtual void RequestFavoritesServerList( AppId_t iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0;
virtual void RequestHistoryServerList( AppId_t iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0;
virtual void RequestSpectatorServerList( AppId_t iApp, MatchMakingKeyValuePair_t **ppchFilters, uint32 nFilters, ISteamMatchmakingServerListResponse *pRequestServersResponse ) = 0;
// Get details on a given server in the list, you can get the valid range of index
// values by calling GetServerCount(). You will also receive index values in
// ISteamMatchmakingServerListResponse::ServerResponded() callbacks
virtual gameserveritem_t *GetServerDetails( EMatchMakingType eType, int iServer ) = 0;
// Cancel an request which is operation on the given list type. You should call this to cancel
// any in-progress requests before destructing a callback object that may have been passed
// to one of the above list request calls. Not doing so may result in a crash when a callback
// occurs on the destructed object.
virtual void CancelQuery( EMatchMakingType eType ) = 0;
// Ping every server in your list again but don't update the list of servers
virtual void RefreshQuery( EMatchMakingType eType ) = 0;
// Returns true if the list is currently refreshing its server list
virtual bool IsRefreshing( EMatchMakingType eType ) = 0;
// How many servers in the given list, GetServerDetails above takes 0... GetServerCount() - 1
virtual int GetServerCount( EMatchMakingType eType ) = 0;
// Refresh a single server inside of a query (rather than all the servers )
virtual void RefreshServer( EMatchMakingType eType, int iServer ) = 0;
//-----------------------------------------------------------------------------
// Queries to individual servers directly via IP/Port
//-----------------------------------------------------------------------------
// Request updated ping time and other details from a single server
virtual HServerQuery PingServer( uint32 unIP, uint16 usPort, ISteamMatchmakingPingResponse *pRequestServersResponse ) = 0;
// Request the list of players currently playing on a server
virtual HServerQuery PlayerDetails( uint32 unIP, uint16 usPort, ISteamMatchmakingPlayersResponse *pRequestServersResponse ) = 0;
// Request the list of rules that the server is running (See ISteamMasterServerUpdater->SetKeyValue() to set the rules server side)
virtual HServerQuery ServerRules( uint32 unIP, uint16 usPort, ISteamMatchmakingRulesResponse *pRequestServersResponse ) = 0;
// Cancel an outstanding Ping/Players/Rules query from above. You should call this to cancel
// any in-progress requests before destructing a callback object that may have been passed
// to one of the above calls to avoid crashing when callbacks occur.
virtual void CancelServerQuery( HServerQuery hServerQuery ) = 0;
};
#define STEAMMATCHMAKINGSERVERS_INTERFACE_VERSION "SteamMatchMakingServers001"
//-----------------------------------------------------------------------------
// Callbacks for ISteamMatchmaking which go through the regular Steam callback registration system
//-----------------------------------------------------------------------------
// game server flags
const uint32 k_unFavoriteFlagNone = 0x00;
const uint32 k_unFavoriteFlagFavorite = 0x01; // this game favorite entry is for the favorites list
const uint32 k_unFavoriteFlagHistory = 0x02; // this game favorite entry is for the history list
// callbacks
//-----------------------------------------------------------------------------
// Purpose: a server was added/removed from the favorites list, you should refresh now
//-----------------------------------------------------------------------------
struct FavoritesListChanged_t
{
enum { k_iCallback = k_iSteamMatchmakingCallbacks + 2 };
uint32 m_nIP; // an IP of 0 means reload the whole list, any other value means just one server
uint32 m_nQueryPort;
uint32 m_nConnPort;
uint32 m_nAppID;
uint32 m_nFlags;
bool m_bAdd; // true if this is adding the entry, otherwise it is a remove
};
//-----------------------------------------------------------------------------
// Purpose: Someone has invited you to join a Lobby
//-----------------------------------------------------------------------------
struct LobbyInvite_t
{
enum { k_iCallback = k_iSteamMatchmakingCallbacks + 3 };
uint64 m_ulSteamIDUser; // Steam ID of the person making the invite
uint64 m_ulSteamIDLobby; // Steam ID of the Lobby
};
//-----------------------------------------------------------------------------
// Purpose: Sent on entering a Lobby
// m_EChatRoomEnterResponse will be set to k_EChatRoomEnterResponseSuccess on success,
// or a higher value on failure (see enum EChatRoomEnterResponse)
//-----------------------------------------------------------------------------
struct LobbyEnter_t
{
enum { k_iCallback = k_iSteamMatchmakingCallbacks + 4 };
uint64 m_ulSteamIDLobby; // SteamID of the Lobby you have entered
uint32 m_rgfChatPermissions; // Permissions of the current user
bool m_bLocked; // If true, then only invited users may join
uint32 m_EChatRoomEnterResponse; // EChatRoomEnterResponse
};
//-----------------------------------------------------------------------------
// Purpose: The lobby metadata has changed
// if m_ulSteamIDMember is the steamID of a lobby member, use GetLobbyMemberData() to access per-user details
// if m_ulSteamIDMember == m_ulSteamIDLobby, use GetLobbyData() to access lobby metadata
//-----------------------------------------------------------------------------
struct LobbyDataUpdate_t
{
enum { k_iCallback = k_iSteamMatchmakingCallbacks + 5 };
uint64 m_ulSteamIDLobby; // steamID of the Lobby
uint64 m_ulSteamIDMember; // steamID of the member whose data changed, or the room itself
};
//-----------------------------------------------------------------------------
// Purpose: The lobby chat room state has changed
// this is usually sent when a user has joined or left the lobby
//-----------------------------------------------------------------------------
struct LobbyChatUpdate_t
{
enum { k_iCallback = k_iSteamMatchmakingCallbacks + 6 };
uint64 m_ulSteamIDLobby; // Lobby ID
uint64 m_ulSteamIDUserChanged; // user who's status in the lobby just changed - can be recipient
uint64 m_ulSteamIDMakingChange; // Chat member who made the change (different from SteamIDUserChange if kicking, muting, etc.)
// for example, if one user kicks another from the lobby, this will be set to the id of the user who initiated the kick
uint32 m_rgfChatMemberStateChange; // bitfield of EChatMemberStateChange values
};
//-----------------------------------------------------------------------------
// Purpose: A chat message for this lobby has been sent
// use GetLobbyChatEntry( m_iChatID ) to retrieve the contents of this message
//-----------------------------------------------------------------------------
struct LobbyChatMsg_t
{
enum { k_iCallback = k_iSteamMatchmakingCallbacks + 7 };
uint64 m_ulSteamIDLobby; // the lobby id this is in
uint64 m_ulSteamIDUser; // steamID of the user who has sent this message
uint8 m_eChatEntryType; // type of message
uint32 m_iChatID; // index of the chat entry to lookup
};
//-----------------------------------------------------------------------------
// Purpose: A game created a game for all the members of the lobby to join,
// as triggered by a SetLobbyGameServer()
// it's up to the individual clients to take action on this; the usual
// game behavior is to leave the lobby and connect to the specified game server
//-----------------------------------------------------------------------------
struct LobbyGameCreated_t
{
enum { k_iCallback = k_iSteamMatchmakingCallbacks + 9 };
uint64 m_ulSteamIDLobby; // the lobby we were in
uint64 m_ulSteamIDGameServer; // the new game server that has been created or found for the lobby members
uint32 m_unIP; // IP & Port of the game server (if any)
uint16 m_usPort;
};
//-----------------------------------------------------------------------------
// Purpose: Number of matching lobbies found
// iterate the returned lobbies with GetLobbyByIndex(), from values 0 to m_nLobbiesMatching-1
//-----------------------------------------------------------------------------
struct LobbyMatchList_t
{
enum { k_iCallback = k_iSteamMatchmakingCallbacks + 10 };
uint32 m_nLobbiesMatching; // Number of lobbies that matched search criteria and we have SteamIDs for
};
//-----------------------------------------------------------------------------
// Purpose: Called when the lobby is being forcefully closed
// lobby details functions will no longer be updated
//-----------------------------------------------------------------------------
struct LobbyClosing_t
{
enum { k_iCallback = k_iSteamMatchmakingCallbacks + 11 };
uint64 m_ulSteamIDLobby; // Lobby
};
//-----------------------------------------------------------------------------
// Purpose: Called when the local user has been kicked from the lobby
// lobby details functions will no longer be updated
//-----------------------------------------------------------------------------
struct LobbyKicked_t
{
enum { k_iCallback = k_iSteamMatchmakingCallbacks + 12 };
uint64 m_ulSteamIDLobby; // Lobby
uint64 m_ulSteamIDAdmin; // User who kicked you
};
//-----------------------------------------------------------------------------
// Purpose: Result of our request to create a Lobby
// m_eResult == k_EResultOK on success
// at this point, the local user may not have finishing joining this lobby;
// game code should wait until the subsequent LobbyEnter_t callback is received
//-----------------------------------------------------------------------------
struct LobbyCreated_t
{
enum { k_iCallback = k_iSteamMatchmakingCallbacks + 13 };
EResult m_eResult; // Result
uint64 m_ulSteamIDLobby; // chat room, zero if failed
};
#endif // ISTEAMMATCHMAKING
+135
View File
@@ -0,0 +1,135 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose: interface to steam managing network connections between game clients & servers
//
//=============================================================================
#ifndef ISTEAMNETWORKING
#define ISTEAMNETWORKING
#ifdef _WIN32
#pragma once
#endif
#include "steamtypes.h"
#include "steamclientpublic.h"
// handle to a socket
typedef uint32 SNetSocket_t;
typedef uint32 SNetListenSocket_t;
// connection progress indicators
enum ESNetSocketState
{
k_ESNetSocketStateInvalid = 0,
// communication is valid
k_ESNetSocketStateConnected = 1,
// states while establishing a connection
k_ESNetSocketStateInitiated = 10, // the connection state machine has started
// p2p connections
k_ESNetSocketStateLocalCandidatesFound = 11, // we've found our local IP info
k_ESNetSocketStateReceivedRemoteCandidates = 12,// we've received information from the remote machine, via the Steam back-end, about their IP info
// direct connections
k_ESNetSocketStateChallengeHandshake = 15, // we've received a challenge packet from the server
// failure states
k_ESNetSocketStateDisconnecting = 21, // the API shut it down, and we're in the process of telling the other end
k_ESNetSocketStateLocalDisconnect = 22, // the API shut it down, and we've completed shutdown
k_ESNetSocketStateTimeoutDuringConnect = 23, // we timed out while trying to creating the connection
k_ESNetSocketStateRemoteEndDisconnected = 24, // the remote end has disconnected from us
k_ESNetSocketStateConnectionBroken = 25, // connection has been broken; either the other end has disappeared or our local network connection has broke
};
//-----------------------------------------------------------------------------
// Purpose: Functions for making connections and sending data between clients,
// traversing NAT's where possible
//-----------------------------------------------------------------------------
class ISteamNetworking
{
public:
// creates a socket and listens others to connect
// will trigger a SocketStatusCallback_t callback on another client connecting
// nVirtualP2PPort is the unique ID that the client will connect to, in case you have multiple ports
// this can usually just be 0 unless you want multiple sets of connections
// unIP is the local IP address to bind to
// pass in 0 if you just want the default local IP
// unPort is the port to use
// pass in 0 if you don't want users to be able to connect via IP/Port, but expect to be always peer-to-peer connections only
virtual SNetListenSocket_t CreateListenSocket( int nVirtualP2PPort, uint32 nIP, uint16 nPort ) = 0;
// creates a socket and begin connection to a remote destination
// can connect via a known steamID (client or game server), or directly to an IP
// on success will trigger a SocketConnectCallback_t callback
// on failure or timeout will trigger a SocketConnectionFailureCallback_t callback
virtual SNetSocket_t CreateP2PConnectionSocket( CSteamID steamIDTarget, int nVirtualPort, int nTimeoutSec ) = 0;
virtual SNetSocket_t CreateConnectionSocket( uint32 nIP, uint16 nPort, int nTimeoutSec ) = 0;
// disconnects the connection to the socket, if any, and invalidates the handle
// any unread data on the socket will be thrown away
// if bNotifyRemoteEnd is set, socket will not be completely destroyed until the remote end acknowledges the disconnect
virtual bool DestroySocket( SNetSocket_t hSocket, bool bNotifyRemoteEnd ) = 0;
// destroying a listen socket will automatically kill all the regular sockets generated from it
virtual bool DestroyListenSocket( SNetListenSocket_t hSocket, bool bNotifyRemoteEnd ) = 0;
// sending data
// must be a handle to a connected socket
// data size cannot be more than 8k, although in UDP mode (default),
// it's recommended packets be no larger than 1300 bytes
// use the reliable flag with caution; although the resend rate is pretty aggressive,
// it can still cause stalls in receiving data (like TCP)
virtual bool SendDataOnSocket( SNetSocket_t hSocket, void *pubData, uint32 cubData, bool bReliable ) = 0;
// receiving data
// returns false if there is no data remaining
// fills out *pcubMsgSize with the size of the next message, in bytes
virtual bool IsDataAvailableOnSocket( SNetSocket_t hSocket, uint32 *pcubMsgSize ) = 0;
// fills in pubDest with the contents of the message
// messages are always complete, of the same size as was sent (i.e. packetized, not streaming)
// if *pcubMsgSize < cubDest, only partial data is written
// returns false if no data is available
virtual bool RetrieveDataFromSocket( SNetSocket_t hSocket, void *pubDest, uint32 cubDest, uint32 *pcubMsgSize ) = 0;
// checks for data from any socket that has been connected off this listen socket
// returns false if there is no data remaining
// fills out *pcubMsgSize with the size of the next message, in bytes
// fills out *phSocket with the socket that data is available on
virtual bool IsDataAvailable( SNetListenSocket_t hListenSocket, uint32 *pcubMsgSize, SNetSocket_t *phSocket ) = 0;
// retrieves data from any socket that has been connected off this listen socket
// fills in pubDest with the contents of the message
// messages are always complete, of the same size as was sent (i.e. packetized, not streaming)
// if *pcubMsgSize < cubDest, only partial data is written
// returns false if no data is available
// fills out *phSocket with the socket that data is available on
virtual bool RetrieveData( SNetListenSocket_t hListenSocket, void *pubDest, uint32 cubDest, uint32 *pcubMsgSize, SNetSocket_t *phSocket ) = 0;
// returns information about the specified socket, filling out the contents of the pointers
virtual bool GetSocketInfo( SNetSocket_t hSocket, CSteamID *pSteamIDRemote, int *peSocketStatus, uint32 *punIPRemote, uint16 *punPortRemote ) = 0;
// returns which local port the listen socket is bound to
// *pnIP and *pnPort will be 0 if the socket is set to listen for P2P connections only
virtual bool GetListenSocketInfo( SNetListenSocket_t hListenSocket, uint32 *pnIP, uint16 *pnPort ) = 0;
};
#define STEAMNETWORKING_INTERFACE_VERSION "SteamNetworking001"
// callback notification - status of a socket has changed
struct SocketStatusCallback_t
{
enum { k_iCallback = k_iSteamNetworkingCallbacks + 1 };
SNetSocket_t m_hSocket; // the socket used to send/receive data to the remote host
SNetListenSocket_t m_hListenSocket; // this is the server socket that we were listening on; NULL if this was an outgoing connection
CSteamID m_steamIDRemote; // remote steamID we have connected to, if it has one
int m_eSNetSocketState; // socket state, ESNetSocketState
};
#endif // ISTEAMNETWORKING
+150
View File
@@ -0,0 +1,150 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose: interface to user account information in Steam
//
//=============================================================================
#ifndef ISTEAMUSER_H
#define ISTEAMUSER_H
#ifdef _WIN32
#pragma once
#endif
#include "isteamclient.h"
// structure that contains client callback data
// see callbacks documentation for more details
struct CallbackMsg_t
{
HSteamUser m_hSteamUser;
int m_iCallback;
uint8 *m_pubParam;
int m_cubParam;
};
// reference to a steam call, to filter results by
typedef int32 HSteamCall;
//-----------------------------------------------------------------------------
// Purpose: Functions for accessing and manipulating a steam account
// associated with one client instance
//-----------------------------------------------------------------------------
class ISteamUser
{
public:
// returns the HSteamUser this interface represents
// this is only used internally by the API, and by a few select interfaces that support multi-user
virtual HSteamUser GetHSteamUser() = 0;
// returns true if the Steam client current has a live connection to the Steam servers.
// If false, it means there is no active connection due to either a networking issue on the local machine, or the Steam server is down/busy.
// The Steam client will automatically be trying to recreate the connection as often as possible.
virtual bool BLoggedOn() = 0;
// returns the CSteamID of the account currently logged into the Steam client
// a CSteamID is a unique identifier for an account, and used to differentiate users in all parts of the Steamworks API
virtual CSteamID GetSteamID() = 0;
// Multiplayer Authentication functions
// InitiateGameConnection() starts the state machine for authenticating the game client with the game server
// It is the client portion of a three-way handshake between the client, the game server, and the steam servers
//
// Parameters:
// void *pAuthBlob - a pointer to empty memory that will be filled in with the authentication token.
// int cbMaxAuthBlob - the number of bytes of allocated memory in pBlob. Should be at least 2048 bytes.
// CSteamID steamIDGameServer - the steamID of the game server, received from the game server by the client
// CGameID gameID - the ID of the current game. For games without mods, this is just CGameID( <appID> )
// uint32 unIPServer, uint16 usPortServer - the IP address of the game server
// bool bSecure - whether or not the client thinks that the game server is reporting itself as secure (i.e. VAC is running)
//
// return value - returns the number of bytes written to pBlob. If the return is 0, then the buffer passed in was too small, and the call has failed
// The contents of pBlob should then be sent to the game server, for it to use to complete the authentication process.
virtual int InitiateGameConnection( void *pAuthBlob, int cbMaxAuthBlob, CSteamID steamIDGameServer, CGameID gameID, uint32 unIPServer, uint16 usPortServer, bool bSecure ) = 0;
// notify of disconnect
// needs to occur when the game client leaves the specified game server, needs to match with the InitiateGameConnection() call
virtual void TerminateGameConnection( uint32 unIPServer, uint16 usPortServer ) = 0;
// Legacy functions
// used by only a few games to track usage events
virtual void TrackAppUsageEvent( CGameID gameID, int eAppUsageEvent, const char *pchExtraInfo = "" ) = 0;
// legacy authentication support - need to be called if the game server rejects the user with a 'bad ticket' error
// this is only needed under very specific circumstances
virtual void RefreshSteam2Login() = 0;
};
#define STEAMUSER_INTERFACE_VERSION "SteamUser009"
// callbacks
//-----------------------------------------------------------------------------
// Purpose: called when a connections to the Steam back-end has been established
// this means the Steam client now has a working connection to the Steam servers
// usually this will have occurred before the game has launched, and should
// only be seen if the user has dropped connection due to a networking issue
// or a Steam server update
//-----------------------------------------------------------------------------
struct SteamServersConnected_t
{
enum { k_iCallback = k_iSteamUserCallbacks + 1 };
};
//-----------------------------------------------------------------------------
// Purpose: called when a connection attempt has failed
// this will occur periodically if the Steam client is not connected,
// and has failed in it's retry to establish a connection
//-----------------------------------------------------------------------------
struct SteamServerConnectFailure_t
{
enum { k_iCallback = k_iSteamUserCallbacks + 2 };
EResult m_eResult;
};
//-----------------------------------------------------------------------------
// Purpose: called if the client has lost connection to the Steam servers
// real-time services will be disabled until a matching SteamServersConnected_t has been posted
//-----------------------------------------------------------------------------
struct SteamServersDisconnected_t
{
enum { k_iCallback = k_iSteamUserCallbacks + 3 };
EResult m_eResult;
};
//-----------------------------------------------------------------------------
// Purpose: Sent by the Steam server to the client telling it to disconnect from the specified game server,
// which it may be in the process of or already connected to.
// The game client should immediately disconnect upon receiving this message.
// This can usually occur if the user doesn't have rights to play on the game server.
//-----------------------------------------------------------------------------
struct ClientGameServerDeny_t
{
enum { k_iCallback = k_iSteamUserCallbacks + 13 };
uint32 m_uAppID;
uint32 m_unGameServerIP;
uint16 m_usGameServerPort;
uint16 m_bSecure;
uint32 m_uReason;
};
//-----------------------------------------------------------------------------
// Purpose: called when the callback system for this client is in an error state (and has flushed pending callbacks)
// When getting this message the client should disconnect from Steam, reset any stored Steam state and reconnect.
// This usually occurs in the rare event the Steam client has some kind of fatal error.
//-----------------------------------------------------------------------------
struct CallbackPipeFailure_t
{
enum { k_iCallback = k_iSteamUserCallbacks + 17 };
};
#endif // ISTEAMUSER_H
+98
View File
@@ -0,0 +1,98 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose: interface to user account information in Steam
//
//=============================================================================
#ifndef ISTEAMUSERSTATS_H
#define ISTEAMUSERSTATS_H
#ifdef _WIN32
#pragma once
#endif
#include "isteamclient.h"
// size limit on stat or achievement name
const uint32 k_cchStatNameMax = 128;
class ISteamUserStats
{
public:
// Ask the server to send down this user's data and achievements for nGameID
virtual bool RequestCurrentStats( ) = 0;
// Data accessors
virtual bool GetStat( const char *pchName, int32 *pData ) = 0;
virtual bool GetStat( const char *pchName, float *pData ) = 0;
// Set / update data
virtual bool SetStat( const char *pchName, int32 nData ) = 0;
virtual bool SetStat( const char *pchName, float fData ) = 0;
virtual bool UpdateAvgRateStat( const char *pchName, float flCountThisSession, double dSessionLength ) = 0;
// Achievement flag accessors
virtual bool GetAchievement( const char *pchName, bool *pbAchieved ) = 0;
virtual bool SetAchievement( const char *pchName ) = 0;
virtual bool ClearAchievement( const char *pchName ) = 0;
// Store the current data on the server, will get a callback when set
// And one callback for every new achievement
virtual bool StoreStats( ) = 0;
// Achievement / GroupAchievement metadata
// Gets the icon of the achievement, which is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set
virtual int GetAchievementIcon( const char *pchName ) = 0;
// Get general attributes (display name / text, etc) for an Achievement
virtual const char *GetAchievementDisplayAttribute( const char *pchName, const char *pchKey ) = 0;
// Achievement progress - triggers an AchievementProgress callback, that is all.
// Calling this w/ N out of N progress will NOT set the achievement, the game must still do that.
virtual bool IndicateAchievementProgress( const char *pchName, uint32 nCurProgress, uint32 nMaxProgress ) = 0;
};
#define STEAMUSERSTATS_INTERFACE_VERSION "STEAMUSERSTATS_INTERFACE_VERSION003"
//-----------------------------------------------------------------------------
// Purpose: called when the latests stats and achievements have been received
// from the server
//-----------------------------------------------------------------------------
struct UserStatsReceived_t
{
enum { k_iCallback = k_iSteamUserStatsCallbacks + 1 };
uint64 m_nGameID; // Game these stats are for
EResult m_eResult; // Success / error fetching the stats
};
//-----------------------------------------------------------------------------
// Purpose: result of a request to store the user stats for a game
//-----------------------------------------------------------------------------
struct UserStatsStored_t
{
enum { k_iCallback = k_iSteamUserStatsCallbacks + 2 };
uint64 m_nGameID; // Game these stats are for
EResult m_eResult; // success / error
};
//-----------------------------------------------------------------------------
// Purpose: result of a request to store the achievements for a game, or an
// "indicate progress" call. If both m_nCurProgress and m_nMaxProgress
// are zero, that means the achievement has been fully unlocked.
//-----------------------------------------------------------------------------
struct UserAchievementStored_t
{
enum { k_iCallback = k_iSteamUserStatsCallbacks + 3 };
uint64 m_nGameID; // Game this is for
bool m_bGroupAchievement; // if this is a "group" achievement
char m_rgchAchievementName[k_cchStatNameMax]; // name of the achievement
uint32 m_nCurProgress; // current progress towards the achievement
uint32 m_nMaxProgress; // "out of" this many
};
#endif // ISTEAMUSER_H
+77
View File
@@ -0,0 +1,77 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose: interface to utility functions in Steam
//
//=============================================================================
#ifndef ISTEAMUTILS_H
#define ISTEAMUTILS_H
#ifdef _WIN32
#pragma once
#endif
#include "isteamclient.h"
//-----------------------------------------------------------------------------
// Purpose: interface to user independent utility functions
//-----------------------------------------------------------------------------
class ISteamUtils
{
public:
// return the number of seconds since the user
virtual uint32 GetSecondsSinceAppActive() = 0;
virtual uint32 GetSecondsSinceComputerActive() = 0;
// the universe this client is connecting to
virtual EUniverse GetConnectedUniverse() = 0;
// Steam server time - in PST, number of seconds since January 1, 1970 (i.e unix time)
virtual uint32 GetServerRealTime() = 0;
// returns the 2 digit ISO 3166-1-alpha-2 format country code this client is running in (as looked up via an IP-to-location database)
// e.g "US" or "UK".
virtual const char *GetIPCountry() = 0;
// returns true if the image exists, and valid sizes were filled out
virtual bool GetImageSize( int iImage, uint32 *pnWidth, uint32 *pnHeight ) = 0;
// returns true if the image exists, and the buffer was successfully filled out
// results are returned in RGBA format
// the destination buffer size should be 4 * height * width * sizeof(char)
virtual bool GetImageRGBA( int iImage, uint8 *pubDest, int nDestBufferSize ) = 0;
// returns the IP of the reporting server for valve - currently only used in Source engine games
virtual bool GetCSERIPPort( uint32 *unIP, uint16 *usPort ) = 0;
// return the amount of battery power left in the current system in % [0..100], 255 for being on AC power
virtual uint8 GetCurrentBatteryPower() = 0;
// returns the appID of the current process
virtual uint32 GetAppID() = 0;
};
#define STEAMUTILS_INTERFACE_VERSION "SteamUtils002"
// callbacks
//-----------------------------------------------------------------------------
// Purpose: The country of the user changed
//-----------------------------------------------------------------------------
struct IPCountry_t
{
enum { k_iCallback = k_iSteamUtilsCallbacks + 1 };
};
//-----------------------------------------------------------------------------
// Purpose: Fired when running on a laptop and less than 10 minutes of battery is left, fires then every minute
//-----------------------------------------------------------------------------
struct LowBatteryPower_t
{
enum { k_iCallback = k_iSteamUtilsCallbacks + 2 };
uint8 m_nMinutesBatteryLeft;
};
#endif // ISTEAMUTILS_H
+235
View File
@@ -0,0 +1,235 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================
#ifndef MATCHMAKINGTYPES_H
#define MATCHMAKINGTYPES_H
#ifdef _WIN32
#pragma once
#endif
#include <stdio.h>
#include <string.h>
struct MatchMakingKeyValuePair_t
{
MatchMakingKeyValuePair_t() { m_szKey[0] = m_szValue[0] = 0; }
MatchMakingKeyValuePair_t( const char *pchKey, const char *pchValue )
{
strncpy( m_szKey, pchKey, sizeof(m_szKey) ); // this is a public header, use basic c library string funcs only!
strncpy( m_szValue, pchValue, sizeof(m_szValue) );
}
char m_szKey[ 256 ];
char m_szValue[ 256 ];
};
enum EMatchMakingServerResponse
{
eServerResponded = 0,
eServerFailedToRespond,
eNoServersListedOnMasterServer // for the Internet query type, returned in response callback if no servers of this type match
};
enum EMatchMakingType
{
eInternetServer = 0,
eLANServer,
eFriendsServer,
eFavoritesServer,
eHistoryServer,
eSpectatorServer,
eInvalidServer
};
// servernetadr_t is all the addressing info the serverbrowser needs to know about a game server,
// namely: its IP, its connection port, and its query port.
class servernetadr_t
{
public:
void Init( unsigned int ip, uint16 usQueryPort, uint16 usConnectionPort );
#ifdef NETADR_H
void Init( const netadr_t &ipAndQueryPort, uint16 usConnectionPort );
netadr_t& GetIPAndQueryPort();
#endif
// Access the query port.
uint16 GetQueryPort() const;
void SetQueryPort( uint16 usPort );
// Access the connection port.
uint16 GetConnectionPort() const;
void SetConnectionPort( uint16 usPort );
// Access the IP
uint32 GetIP() const;
void SetIP( uint32 );
// This gets the 'a.b.c.d:port' string with the connection port (instead of the query port).
const char *GetConnectionAddressString() const;
const char *GetQueryAddressString() const;
// Comparison operators and functions.
bool operator<(const servernetadr_t &netadr) const;
void operator=( const servernetadr_t &that )
{
m_usConnectionPort = that.m_usConnectionPort;
m_usQueryPort = that.m_usQueryPort;
m_unIP = that.m_unIP;
}
private:
const char *ToString( uint32 unIP, uint16 usPort ) const;
uint16 m_usConnectionPort; // (in HOST byte order)
uint16 m_usQueryPort;
uint32 m_unIP;
};
inline void servernetadr_t::Init( unsigned int ip, uint16 usQueryPort, uint16 usConnectionPort )
{
m_unIP = ip;
m_usQueryPort = usQueryPort;
m_usConnectionPort = usConnectionPort;
}
#ifdef NETADR_H
inline void servernetadr_t::Init( const netadr_t &ipAndQueryPort, uint16 usConnectionPort )
{
Init( ipAndQueryPort.GetIP(), ipAndQueryPort.GetPort(), usConnectionPort );
}
inline netadr_t& servernetadr_t::GetIPAndQueryPort()
{
static netadr_t netAdr;
netAdr.SetIP( m_unIP );
netAdr.SetPort( m_usQueryPort );
return netAdr;
}
#endif
inline uint16 servernetadr_t::GetQueryPort() const
{
return m_usQueryPort;
}
inline void servernetadr_t::SetQueryPort( uint16 usPort )
{
m_usQueryPort = usPort;
}
inline uint16 servernetadr_t::GetConnectionPort() const
{
return m_usConnectionPort;
}
inline void servernetadr_t::SetConnectionPort( uint16 usPort )
{
m_usConnectionPort = usPort;
}
inline uint32 servernetadr_t::GetIP() const
{
return m_unIP;
}
inline void servernetadr_t::SetIP( uint32 unIP )
{
m_unIP = unIP;
}
inline const char *servernetadr_t::ToString( uint32 unIP, uint16 usPort ) const
{
static char s[4][64];
static int nBuf = 0;
unsigned char *ipByte = (unsigned char *)&unIP;
_snprintf (s[nBuf], sizeof( s[nBuf] ), "%u.%u.%u.%u:%i", (int)(ipByte[3]), (int)(ipByte[2]), (int)(ipByte[1]), (int)(ipByte[0]), usPort );
const char *pchRet = s[nBuf];
++nBuf;
nBuf %= ( (sizeof(s)/sizeof(s[0])) );
return pchRet;
}
inline const char* servernetadr_t::GetConnectionAddressString() const
{
return ToString( m_unIP, m_usConnectionPort );
}
inline const char* servernetadr_t::GetQueryAddressString() const
{
return ToString( m_unIP, m_usQueryPort );
}
inline bool servernetadr_t::operator<(const servernetadr_t &netadr) const
{
return ( m_unIP < netadr.m_unIP ) || ( m_unIP == netadr.m_unIP && m_usQueryPort < netadr.m_usQueryPort );
}
//-----------------------------------------------------------------------------
// Purpose: Data describing a single server
//-----------------------------------------------------------------------------
class gameserveritem_t
{
public:
gameserveritem_t();
const char* GetName() const;
void SetName( const char *pName );
public:
servernetadr_t m_NetAdr; // IP/Query Port/Connection Port for this server
int m_nPing; // current ping time in milliseconds
bool m_bHadSuccessfulResponse; // server has responded successfully in the past
bool m_bDoNotRefresh; // server is marked as not responding and should no longer be refreshed
char m_szGameDir[32]; // current game directory
char m_szMap[32]; // current map
char m_szGameDescription[64]; // game description
int m_nAppID; // Steam App ID of this server
int m_nPlayers; // current number of players on the server
int m_nMaxPlayers; // Maximum players that can join this server
int m_nBotPlayers; // Number of bots (i.e simulated players) on this server
bool m_bPassword; // true if this server needs a password to join
bool m_bSecure; // Is this server protected by VAC
uint32 m_ulTimeLastPlayed; // time (in unix time) when this server was last played on (for favorite/history servers)
int m_nServerVersion; // server version as reported to Steam
private:
char m_szServerName[64]; // Game server name
// For data added after SteamMatchMaking001 add it here
public:
char m_szGameTags[128]; // the tags this server exposes
};
inline gameserveritem_t::gameserveritem_t()
{
m_szGameDir[0] = m_szMap[0] = m_szGameDescription[0] = m_szServerName[0] = 0;
m_bHadSuccessfulResponse = m_bDoNotRefresh = m_bPassword = m_bSecure = false;
m_nPing = m_nAppID = m_nPlayers = m_nMaxPlayers = m_nBotPlayers = m_ulTimeLastPlayed = m_nServerVersion = 0;
m_szGameTags[0] = 0;
}
inline const char* gameserveritem_t::GetName() const
{
// Use the IP address as the name if nothing is set yet.
if ( m_szServerName[0] == 0 )
return m_NetAdr.GetConnectionAddressString();
else
return m_szServerName;
}
inline void gameserveritem_t::SetName( const char *pName )
{
strncpy( m_szServerName, pName, sizeof( m_szServerName ) );
}
#endif // MATCHMAKINGTYPES_H
+308
View File
@@ -0,0 +1,308 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef STEAM_API_H
#define STEAM_API_H
#ifdef _WIN32
#pragma once
#endif
#include "isteamclient.h"
#include "isteamuser.h"
#include "isteamfriends.h"
#include "isteamutils.h"
#include "isteammatchmaking.h"
#include "isteamuserstats.h"
#include "isteamapps.h"
#include "isteamnetworking.h"
// Steam API export macro
#if defined( _WIN32 ) && !defined( _X360 )
#if defined( STEAM_API_EXPORTS )
#define S_API extern "C" __declspec( dllexport )
#elif defined( STEAM_API_NODLL )
#define S_API extern "C"
#else
#define S_API extern "C" __declspec( dllimport )
#endif // STEAM_API_EXPORTS
#elif defined( _LINUX )
#if defined( STEAM_API_EXPORTS )
#define S_API extern "C" __attribute__ ((visibility("default")))
#else
#define S_API extern "C"
#endif // STEAM_API_EXPORTS
#else // !WIN32
#if defined( STEAM_API_EXPORTS )
#define S_API extern "C"
#else
#define S_API extern "C"
#endif // STEAM_API_EXPORTS
#endif
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
// Steam API setup & shutdown
//
// These functions manage loading, initializing and shutdown of the steamclient.dll
//
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
// S_API void SteamAPI_Init(); (see below)
S_API void SteamAPI_Shutdown();
// crash dump recording functions
S_API void SteamAPI_WriteMiniDump( uint32 uStructuredExceptionCode, void* pvExceptionInfo, uint32 uBuildID );
S_API void SteamAPI_SetMiniDumpComment( const char *pchMsg );
// interface pointers, configured by SteamAPI_Init()
S_API ISteamClient *SteamClient();
//
// VERSION_SAFE_STEAM_API_INTERFACES is usually not necessary, but it provides safety against releasing
// new steam_api.dll's without recompiling/rereleasing modules that use it.
//
// If you use VERSION_SAFE_STEAM_API_INTERFACES, then you should call SteamAPI_InitSafe(). Also, to get the
// Steam interfaces, you must create and Init() a CSteamAPIContext (below) and use the interfaces in there.
//
// If you don't use VERSION_SAFE_STEAM_API_INTERFACES, then you can use SteamAPI_Init() and the SteamXXXX()
// functions below to get at the Steam interfaces.
//
#ifdef VERSION_SAFE_STEAM_API_INTERFACES
S_API bool SteamAPI_InitSafe();
#else
S_API bool SteamAPI_Init();
S_API ISteamUser *SteamUser();
S_API ISteamFriends *SteamFriends();
S_API ISteamUtils *SteamUtils();
S_API ISteamMatchmaking *SteamMatchmaking();
S_API ISteamUserStats *SteamUserStats();
S_API ISteamApps *SteamApps();
S_API ISteamNetworking *SteamNetworking();
S_API ISteamMatchmakingServers *SteamMatchmakingServers();
#endif // VERSION_SAFE_STEAM_API_INTERFACES
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
// steam callback helper functions
//
// The following classes/macros are used to be able to easily multiplex callbacks
// from the Steam API into various objects in the app in a thread-safe manner
//
// These functors are triggered via the SteamAPI_RunCallbacks() function, mapping the callback
// to as many functions/objects as are registered to it
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
S_API void SteamAPI_RunCallbacks();
// functions used by the utility CCallback objects to receive callbacks
S_API void SteamAPI_RegisterCallback( class CCallbackBase *pCallback, int iCallback );
S_API void SteamAPI_UnregisterCallback( class CCallbackBase *pCallback );
//-----------------------------------------------------------------------------
// Purpose: base for callbacks,
// used only by CCallback, shouldn't be used directly
//-----------------------------------------------------------------------------
class CCallbackBase
{
public:
CCallbackBase() { m_nCallbackFlags = 0; }
// don't add a virtual destructor because we export this binary interface across dll's
virtual void Run( void *pvParam ) = 0;
protected:
enum { k_ECallbackFlagsRegistered = 0x01, k_ECallbackFlagsGameServer = 0x02 };
uint8 m_nCallbackFlags;
private:
int m_iCallback;
friend class CCallbackMgr;
};
//-----------------------------------------------------------------------------
// Purpose: maps a steam callback to a class member function
// template params: T = local class, P = parameter struct
//-----------------------------------------------------------------------------
template< class T, class P, bool bGameServer >
class CCallback : private CCallbackBase
{
public:
typedef void (T::*func_t)( P* );
// If you can't support constructing a callback with the correct parameters
// then uncomment the empty constructor below and manually call
// ::Register() for your object
//CCallback() {}
// constructor for initializing this object in owner's constructor
CCallback( T *pObj, func_t func ) : m_pObj( pObj ), m_Func( func )
{
if ( bGameServer )
{
m_nCallbackFlags |= k_ECallbackFlagsGameServer;
}
Register( pObj, func );
}
~CCallback()
{
SteamAPI_UnregisterCallback( this );
}
// manual registration of the callback
void Register( T *pObj, func_t func )
{
m_pObj = pObj;
m_Func = func;
SteamAPI_RegisterCallback( this, P::k_iCallback );
}
private:
virtual void Run( void *pvParam )
{
(m_pObj->*m_Func)( (P *)pvParam );
}
T *m_pObj;
func_t m_Func;
};
// utility macro for declaring the function and callback object together
#define STEAM_CALLBACK( thisclass, func, param, var ) CCallback< thisclass, param, false > var; void func( param *pParam )
#ifdef _WIN32
// disable this warning; this pattern need for steam callback registration
#pragma warning( disable: 4355 ) // 'this' : used in base member initializer list
#endif
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
// steamclient.dll private wrapper functions
//
// The following functions are part of abstracting API access to the steamclient.dll, but should only be used in very specific cases
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
// pumps out all the steam messages, calling the register callback
S_API void Steam_RunCallbacks( HSteamPipe hSteamPipe, bool bGameServerCallbacks );
// register the callback funcs to use to interact with the steam dll
S_API void Steam_RegisterInterfaceFuncs( void *hModule );
// returns the HSteamUser of the last user to dispatch a callback
S_API HSteamUser Steam_GetHSteamUserCurrent();
// returns the filename path of the current running Steam process, used if you need to load an explicit steam dll by name
S_API const char *SteamAPI_GetSteamInstallPath();
#ifdef VERSION_SAFE_STEAM_API_INTERFACES
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
// VERSION_SAFE_STEAM_API_INTERFACES uses CSteamAPIContext to provide interfaces to each module in a way that
// lets them each specify the interface versions they are compiled with.
//
// It's important that these stay inlined in the header so the calling module specifies the interface versions
// for whatever Steam API version it has.
//----------------------------------------------------------------------------------------------------------------------------------------------------------//
S_API HSteamPipe GetHSteamPipe();
S_API HSteamUser GetHSteamUser();
class CSteamAPIContext
{
public:
CSteamAPIContext();
void Clear();
bool Init();
ISteamUser* SteamUser() { return m_pSteamUser; }
ISteamFriends* SteamFriends() { return m_pSteamFriends; }
ISteamUtils* SteamUtils() { return m_pSteamUtils; }
ISteamMatchmaking* SteamMatchmaking() { return m_pSteamMatchmaking; }
ISteamUserStats* SteamUserStats() { return m_pSteamUserStats; }
ISteamApps* SteamApps() { return m_pSteamApps; }
ISteamMatchmakingServers* SteamMatchmakingServers() { return m_pSteamMatchmakingServers; }
ISteamNetworking* SteamNetworking() { return m_pSteamNetworking; }
private:
ISteamUser *m_pSteamUser;
ISteamFriends *m_pSteamFriends;
ISteamUtils *m_pSteamUtils;
ISteamMatchmaking *m_pSteamMatchmaking;
ISteamUserStats *m_pSteamUserStats;
ISteamApps *m_pSteamApps;
ISteamMatchmakingServers *m_pSteamMatchmakingServers;
ISteamNetworking *m_pSteamNetworking;
};
inline CSteamAPIContext::CSteamAPIContext()
{
Clear();
}
inline void CSteamAPIContext::Clear()
{
m_pSteamUser = NULL;
m_pSteamFriends = NULL;
m_pSteamUtils = NULL;
m_pSteamMatchmaking = NULL;
m_pSteamUserStats = NULL;
m_pSteamApps = NULL;
m_pSteamMatchmakingServers = NULL;
m_pSteamNetworking = NULL;
}
// This function must be inlined so the module using steam_api.dll gets the version names they want.
inline bool CSteamAPIContext::Init()
{
if ( !SteamClient() )
return false;
HSteamUser hSteamUser = GetHSteamUser();
HSteamPipe hSteamPipe = GetHSteamPipe();
m_pSteamUser = SteamClient()->GetISteamUser( hSteamUser, hSteamPipe, STEAMUSER_INTERFACE_VERSION );
if ( !m_pSteamUser )
return false;
m_pSteamFriends = SteamClient()->GetISteamFriends( hSteamUser, hSteamPipe, STEAMFRIENDS_INTERFACE_VERSION );
if ( !m_pSteamFriends )
return false;
m_pSteamUtils = SteamClient()->GetISteamUtils( hSteamUser, STEAMUTILS_INTERFACE_VERSION );
if ( !m_pSteamUtils )
return false;
m_pSteamMatchmaking = SteamClient()->GetISteamMatchmaking( hSteamUser, hSteamPipe, STEAMMATCHMAKING_INTERFACE_VERSION );
if ( !m_pSteamMatchmaking )
return false;
m_pSteamMatchmakingServers = SteamClient()->GetISteamMatchmakingServers( hSteamUser, hSteamPipe, STEAMMATCHMAKINGSERVERS_INTERFACE_VERSION );
if ( !m_pSteamMatchmakingServers )
return false;
m_pSteamUserStats = SteamClient()->GetISteamUserStats( hSteamUser, hSteamPipe, STEAMUSERSTATS_INTERFACE_VERSION );
if ( !m_pSteamUserStats )
return false;
m_pSteamApps = SteamClient()->GetISteamApps( hSteamUser, hSteamPipe, STEAMAPPS_INTERFACE_VERSION );
if ( !m_pSteamApps )
return false;
m_pSteamNetworking = SteamClient()->GetISteamNetworking( hSteamUser, hSteamPipe, STEAMNETWORKING_INTERFACE_VERSION );
if ( !m_pSteamNetworking )
return false;
return true;
}
#endif // VERSION_SAFE_STEAM_API_INTERFACES
#endif // STEAM_API_H
+45
View File
@@ -0,0 +1,45 @@
//====== Copyright © 1996-2008, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef STEAM_GAMESERVER_H
#define STEAM_GAMESERVER_H
#ifdef _WIN32
#pragma once
#endif
#include "steam_api.h"
#include "isteamgameserver.h"
#include "isteammasterserverupdater.h"
enum EServerMode
{
eServerModeNoAuthentication = 1, // Don't authenticate user logins and don't list on the server list
eServerModeAuthentication = 2, // Authenticate users, list on the server list, don't run VAC on clients that connect
eServerModeAuthenticationAndSecure = 3, // Authenticate users, list on the server list and VAC protect clients
};
// Note: if you pass MASTERSERVERUPDATERPORT_USEGAMESOCKETSHARE for usQueryPort, then it will use "GameSocketShare" mode,
// which means that the game is responsible for sending and receiving UDP packets for the master
// server updater. See references to GameSocketShare in isteammasterserverupdater.h.
//
// Pass 0 for usGamePort or usSpectatorPort if you're not using that. Then, the master server updater will report
// what's running based on that.
S_API bool SteamGameServer_Init( uint32 unIP, uint16 usPort, uint16 usGamePort, uint16 usSpectatorPort, uint16 usQueryPort, EServerMode eServerMode, int nGameAppId, const char *pchGameDir, const char *pchVersionString );
S_API void SteamGameServer_Shutdown();
S_API void SteamGameServer_RunCallbacks();
S_API bool SteamGameServer_BSecure();
S_API uint64 SteamGameServer_GetSteamID();
S_API ISteamGameServer *SteamGameServer();
S_API ISteamUtils *SteamGameServerUtils();
S_API ISteamMasterServerUpdater *SteamMasterServerUpdater();
S_API ISteamNetworking *SteamGameServerNetworking();
#define STEAM_GAMESERVER_CALLBACK( thisclass, func, param, var ) CCallback< thisclass, param, true > var; void func( param *pParam )
#endif // STEAM_GAMESERVER_H
+732
View File
@@ -0,0 +1,732 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose:
//
//=============================================================================
#ifndef STEAMCLIENTPUBLIC_H
#define STEAMCLIENTPUBLIC_H
#ifdef _WIN32
#pragma once
#endif
//lint -save -e1931 -e1927 -e1924 -e613 -e726
// This header file defines the interface between the calling application and the code that
// knows how to communicate with the connection manager (CM) from the Steam service
// This header file is intended to be portable; ideally this 1 header file plus a lib or dll
// is all you need to integrate the client library into some other tree. So please avoid
// including or requiring other header files if possible. This header should only describe the
// interface layer, no need to include anything about the implementation.
#include "steamtypes.h"
// General result codes
enum EResult
{
k_EResultOK = 1, // success
k_EResultFail = 2, // generic failure
k_EResultNoConnection = 3, // no/failed network connection
// k_EResultNoConnectionRetry = 4, // OBSOLETE - removed
k_EResultInvalidPassword = 5, // password/ticket is invalid
k_EResultLoggedInElsewhere = 6, // same user logged in elsewhere
k_EResultInvalidProtocolVer = 7, // protocol version is incorrect
k_EResultInvalidParam = 8, // a parameter is incorrect
k_EResultFileNotFound = 9, // file was not found
k_EResultBusy = 10, // called method busy - action not taken
k_EResultInvalidState = 11, // called object was in an invalid state
k_EResultInvalidName = 12, // name is invalid
k_EResultInvalidEmail = 13, // email is invalid
k_EResultDuplicateName = 14, // name is not unique
k_EResultAccessDenied = 15, // access is denied
k_EResultTimeout = 16, // operation timed out
k_EResultBanned = 17, // VAC2 banned
k_EResultAccountNotFound = 18, // account not found
k_EResultInvalidSteamID = 19, // steamID is invalid
k_EResultServiceUnavailable = 20, // The requested service is currently unavailable
k_EResultNotLoggedOn = 21, // The user is not logged on
k_EResultPending = 22, // Request is pending (may be in process, or waiting on third party)
k_EResultEncryptionFailure = 23, // Encryption or Decryption failed
k_EResultInsufficientPrivilege = 24, // Insufficient privilege
k_EResultLimitExceeded = 25, // Too much of a good thing
k_EResultRevoked = 26, // Access has been revoked (used for revoked guest passes)
k_EResultExpired = 27, // License/Guest pass the user is trying to access is expired
k_EResultAlreadyRedeemed = 28, // Guest pass has already been redeemed by account, cannot be acked again
k_EResultDuplicateRequest = 29, // The request is a duplicate and the action has already occurred in the past, ignored this time
k_EResultAlreadyOwned = 30, // All the games in this guest pass redemption request are already owned by the user
k_EResultIPNotFound = 31, // IP address not found
k_EResultPersistFailed = 32, // failed to write change to the data store
k_EResultLockingFailed = 33, // failed to acquire access lock for this operation
k_EResultLogonSessionReplaced = 34,
k_EResultConnectFailed = 35,
k_EResultHandshakeFailed = 36,
k_EResultIOFailure = 37,
k_EResultRemoteDisconnect = 38,
k_EResultShoppingCartNotFound = 39, // failed to find the shopping cart requested
k_EResultBlocked = 40, // a user didn't allow it
k_EResultIgnored = 41, // target is ignoring sender
};
// Result codes to GSHandleClientDeny/Kick
typedef enum
{
k_EDenyInvalidVersion = 1,
k_EDenyGeneric = 2,
k_EDenyNotLoggedOn = 3,
k_EDenyNoLicense = 4,
k_EDenyCheater = 5,
k_EDenyLoggedInElseWhere = 6,
k_EDenyUnknownText = 7,
k_EDenyIncompatibleAnticheat = 8,
k_EDenyMemoryCorruption = 9,
k_EDenyIncompatibleSoftware = 10,
k_EDenySteamConnectionLost = 11,
k_EDenySteamConnectionError = 12,
k_EDenySteamResponseTimedOut = 13,
k_EDenySteamValidationStalled = 14,
} EDenyReason;
// Steam universes. Each universe is a self-contained Steam instance.
enum EUniverse
{
k_EUniverseInvalid = 0,
k_EUniversePublic = 1,
k_EUniverseBeta = 2,
k_EUniverseInternal = 3,
k_EUniverseDev = 4,
k_EUniverseRC = 5,
k_EUniverseMax
};
// Steam account types
enum EAccountType
{
k_EAccountTypeInvalid = 0,
k_EAccountTypeIndividual = 1, // single user account
k_EAccountTypeMultiseat = 2, // multiseat (e.g. cybercafe) account
k_EAccountTypeGameServer = 3, // game server account
k_EAccountTypeAnonGameServer = 4, // anonymous game server account
k_EAccountTypePending = 5, // pending
k_EAccountTypeContentServer = 6, // content server
k_EAccountTypeClan = 7,
k_EAccountTypeChat = 8,
k_EAccountTypeP2PSuperSeeder = 9, // a fake steamid used by superpeers to seed content to users of Steam P2P stuff
k_EAccountTypeAnonUser = 10,
// Max of 16 items in this field
k_EAccountTypeMax
};
//-----------------------------------------------------------------------------
// types of user game stats fields
// WARNING: DO NOT RENUMBER EXISTING VALUES - STORED IN DATABASE
//-----------------------------------------------------------------------------
enum ESteamUserStatType
{
k_ESteamUserStatTypeINVALID = 0,
k_ESteamUserStatTypeINT = 1,
k_ESteamUserStatTypeFLOAT = 2,
// Read as FLOAT, set with count / session length
k_ESteamUserStatTypeAVGRATE = 3,
k_ESteamUserStatTypeACHIEVEMENTS = 4,
k_ESteamUserStatTypeGROUPACHIEVEMENTS = 5,
};
//-----------------------------------------------------------------------------
// Purpose: Chat Entry Types (previously was only friend-to-friend message types)
//-----------------------------------------------------------------------------
enum EChatEntryType
{
k_EChatEntryTypeChatMsg = 1, // Normal text message from another user
k_EChatEntryTypeTyping = 2, // Another user is typing (not used in multi-user chat)
k_EChatEntryTypeInviteGame = 3, // Invite from other user into that users current game
k_EChatEntryTypeEmote = 4, // text emote message
k_EChatEntryTypeLobbyGameStart = 5, // lobby game is starting
// Above are previous FriendMsgType entries, now merged into more generic chat entry types
};
//-----------------------------------------------------------------------------
// Purpose: Chat Room Enter Responses
//-----------------------------------------------------------------------------
enum EChatRoomEnterResponse
{
k_EChatRoomEnterResponseSuccess = 1, // Success
k_EChatRoomEnterResponseDoesntExist = 2, // Chat doesn't exist (probably closed)
k_EChatRoomEnterResponseNotAllowed = 3, // General Denied - You don't have the permissions needed to join the chat
k_EChatRoomEnterResponseFull = 4, // Chat room has reached its maximum size
k_EChatRoomEnterResponseError = 5, // Unexpected Error
k_EChatRoomEnterResponseBanned = 6, // You are banned from this chat room and may not join
};
typedef void (*PFNLegacyKeyRegistration)( const char *pchCDKey, const char *pchInstallPath );
typedef bool (*PFNLegacyKeyInstalled)();
#pragma pack( push, 1 )
// Steam ID structure (64 bits total)
class CSteamID
{
public:
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CSteamID()
{
m_unAccountID = 0;
m_EAccountType = k_EAccountTypeInvalid;
m_EUniverse = k_EUniverseInvalid;
m_unAccountInstance = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
// Input : unAccountID - 32-bit account ID
// eUniverse - Universe this account belongs to
// eAccountType - Type of account
//-----------------------------------------------------------------------------
CSteamID( uint32 unAccountID, EUniverse eUniverse, EAccountType eAccountType )
{
Set( unAccountID, eUniverse, eAccountType );
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
// Input : unAccountID - 32-bit account ID
// unAccountInstance - instance
// eUniverse - Universe this account belongs to
// eAccountType - Type of account
//-----------------------------------------------------------------------------
CSteamID( uint32 unAccountID, unsigned int unAccountInstance, EUniverse eUniverse, EAccountType eAccountType )
{
#if defined(_SERVER) && defined(Assert)
Assert( ! ( ( k_EAccountTypeIndividual == eAccountType ) && ( 1 != unAccountInstance ) ) ); // enforce that for individual accounts, instance is always 1
#endif // _SERVER
InstancedSet( unAccountID, unAccountInstance, eUniverse, eAccountType );
}
//-----------------------------------------------------------------------------
// Purpose: Constructor
// Input : ulSteamID - 64-bit representation of a Steam ID
// Note: Will not accept a uint32 or int32 as input, as that is a probable mistake.
// See the stubbed out overloads in the private: section for more info.
//-----------------------------------------------------------------------------
CSteamID( uint64 ulSteamID )
{
SetFromUint64( ulSteamID );
}
//-----------------------------------------------------------------------------
// Purpose: Sets parameters for steam ID
// Input : unAccountID - 32-bit account ID
// eUniverse - Universe this account belongs to
// eAccountType - Type of account
//-----------------------------------------------------------------------------
void Set( uint32 unAccountID, EUniverse eUniverse, EAccountType eAccountType )
{
m_unAccountID = unAccountID;
m_EUniverse = eUniverse;
m_EAccountType = eAccountType;
m_unAccountInstance = 1;
}
//-----------------------------------------------------------------------------
// Purpose: Sets parameters for steam ID
// Input : unAccountID - 32-bit account ID
// eUniverse - Universe this account belongs to
// eAccountType - Type of account
//-----------------------------------------------------------------------------
void InstancedSet( uint32 unAccountID, uint32 unInstance, EUniverse eUniverse, EAccountType eAccountType )
{
m_unAccountID = unAccountID;
m_EUniverse = eUniverse;
m_EAccountType = eAccountType;
m_unAccountInstance = unInstance;
}
//-----------------------------------------------------------------------------
// Purpose: Initializes a steam ID from its 52 bit parts and universe/type
// Input : ulIdentifier - 52 bits of goodness
//-----------------------------------------------------------------------------
void FullSet( uint64 ulIdentifier, EUniverse eUniverse, EAccountType eAccountType )
{
m_unAccountID = ( ulIdentifier & 0xFFFFFFFF ); // account ID is low 32 bits
m_unAccountInstance = ( ( ulIdentifier >> 32 ) & 0xFFFFF ); // account instance is next 20 bits
m_EUniverse = eUniverse;
m_EAccountType = eAccountType;
}
//-----------------------------------------------------------------------------
// Purpose: Initializes a steam ID from its 64-bit representation
// Input : ulSteamID - 64-bit representation of a Steam ID
//-----------------------------------------------------------------------------
void SetFromUint64( uint64 ulSteamID )
{
m_unAccountID = ( ulSteamID & 0xFFFFFFFF ); // account ID is low 32 bits
m_unAccountInstance = ( ( ulSteamID >> 32 ) & 0xFFFFF ); // account instance is next 20 bits
m_EAccountType = ( EAccountType ) ( ( ulSteamID >> 52 ) & 0xF ); // type is next 4 bits
m_EUniverse = ( EUniverse ) ( ( ulSteamID >> 56 ) & 0xFF ); // universe is next 8 bits
}
#if defined( INCLUDED_STEAM_COMMON_STEAMCOMMON_H )
//-----------------------------------------------------------------------------
// Purpose: Initializes a steam ID from a Steam2 ID structure
// Input: pTSteamGlobalUserID - Steam2 ID to convert
// eUniverse - universe this ID belongs to
//-----------------------------------------------------------------------------
void SetFromSteam2( TSteamGlobalUserID *pTSteamGlobalUserID, EUniverse eUniverse )
{
m_unAccountID = pTSteamGlobalUserID->m_SteamLocalUserID.Split.Low32bits * 2 +
pTSteamGlobalUserID->m_SteamLocalUserID.Split.High32bits;
m_EUniverse = eUniverse; // set the universe
m_EAccountType = k_EAccountTypeIndividual; // Steam 2 accounts always map to account type of individual
m_unAccountInstance = 1; // individual accounts always have an account instance ID of 1
}
//-----------------------------------------------------------------------------
// Purpose: Fills out a Steam2 ID structure
// Input: pTSteamGlobalUserID - Steam2 ID to write to
//-----------------------------------------------------------------------------
void ConvertToSteam2( TSteamGlobalUserID *pTSteamGlobalUserID ) const
{
// only individual accounts have any meaning in Steam 2, only they can be mapped
// Assert( m_EAccountType == k_EAccountTypeIndividual );
pTSteamGlobalUserID->m_SteamInstanceID = 0;
pTSteamGlobalUserID->m_SteamLocalUserID.Split.High32bits = m_unAccountID % 2;
pTSteamGlobalUserID->m_SteamLocalUserID.Split.Low32bits = m_unAccountID / 2;
}
#endif // defined( INCLUDED_STEAM_COMMON_STEAMCOMMON_H )
//-----------------------------------------------------------------------------
// Purpose: Converts steam ID to its 64-bit representation
// Output : 64-bit representation of a Steam ID
//-----------------------------------------------------------------------------
uint64 ConvertToUint64() const
{
return (uint64) ( ( ( (uint64) m_EUniverse ) << 56 ) + ( ( (uint64) m_EAccountType ) << 52 ) +
( ( (uint64) m_unAccountInstance ) << 32 ) + m_unAccountID );
}
//-----------------------------------------------------------------------------
// Purpose: Converts the static parts of a steam ID to a 64-bit representation.
// For multiseat accounts, all instances of that account will have the
// same static account key, so they can be grouped together by the static
// account key.
// Output : 64-bit static account key
//-----------------------------------------------------------------------------
uint64 GetStaticAccountKey() const
{
// note we do NOT include the account instance (which is a dynamic property) in the static account key
return (uint64) ( ( ( (uint64) m_EUniverse ) << 56 ) + ((uint64) m_EAccountType << 52 ) + m_unAccountID );
}
//-----------------------------------------------------------------------------
// Purpose: create an anonymous game server login to be filled in by the AM
//-----------------------------------------------------------------------------
void CreateBlankAnonLogon( EUniverse eUniverse )
{
m_unAccountID = 0;
m_EAccountType = k_EAccountTypeAnonGameServer;
m_EUniverse = eUniverse;
m_unAccountInstance = 0;
}
//-----------------------------------------------------------------------------
// Purpose: create an anonymous game server login to be filled in by the AM
//-----------------------------------------------------------------------------
void CreateBlankAnonUserLogon( EUniverse eUniverse )
{
m_unAccountID = 0;
m_EAccountType = k_EAccountTypeAnonUser;
m_EUniverse = eUniverse;
m_unAccountInstance = 0;
}
//-----------------------------------------------------------------------------
// Purpose: Is this an anonymous game server login that will be filled in?
//-----------------------------------------------------------------------------
bool BBlankAnonAccount() const
{
return m_unAccountID == 0 && BAnonAccount() && m_unAccountInstance == 0;
}
//-----------------------------------------------------------------------------
// Purpose: Is this a game server account id?
//-----------------------------------------------------------------------------
bool BGameServerAccount() const
{
return m_EAccountType == k_EAccountTypeGameServer || m_EAccountType == k_EAccountTypeAnonGameServer;
}
//-----------------------------------------------------------------------------
// Purpose: Is this a content server account id?
//-----------------------------------------------------------------------------
bool BContentServerAccount() const
{
return m_EAccountType == k_EAccountTypeContentServer;
}
//-----------------------------------------------------------------------------
// Purpose: Is this a clan account id?
//-----------------------------------------------------------------------------
bool BClanAccount() const
{
return m_EAccountType == k_EAccountTypeClan;
}
//-----------------------------------------------------------------------------
// Purpose: Is this a chat account id?
//-----------------------------------------------------------------------------
bool BChatAccount() const
{
return m_EAccountType == k_EAccountTypeChat;
}
//-----------------------------------------------------------------------------
// Purpose: Is this an individual user account id?
//-----------------------------------------------------------------------------
bool BIndividualAccount() const
{
return m_EAccountType == k_EAccountTypeIndividual;
}
//-----------------------------------------------------------------------------
// Purpose: Is this an anonymous account?
//-----------------------------------------------------------------------------
bool BAnonAccount() const
{
return m_EAccountType == k_EAccountTypeAnonUser || m_EAccountType == k_EAccountTypeAnonGameServer;
}
// simple accessors
void SetAccountID( uint32 unAccountID ) { m_unAccountID = unAccountID; }
uint32 GetAccountID() const { return m_unAccountID; }
uint32 GetUnAccountInstance() const { return m_unAccountInstance; }
EAccountType GetEAccountType() const { return ( EAccountType ) m_EAccountType; }
EUniverse GetEUniverse() const { return m_EUniverse; }
void SetEUniverse( EUniverse eUniverse ) { m_EUniverse = eUniverse; }
bool IsValid() const { return ( m_EAccountType != k_EAccountTypeInvalid && m_EUniverse != k_EUniverseInvalid ); }
// this set of functions is hidden, will be moved out of class
explicit CSteamID( const char *pchSteamID, EUniverse eDefaultUniverse = k_EUniverseInvalid );
char * Render() const; // renders this steam ID to string
static char * Render( uint64 ulSteamID ); // static method to render a uint64 representation of a steam ID to a string
void SetFromString( const char *pchSteamID, EUniverse eDefaultUniverse );
bool SetFromSteam2String( const char *pchSteam2ID, EUniverse eUniverse );
bool operator==( const CSteamID &val ) const
{
return ( ( val.m_unAccountID == m_unAccountID ) && ( val.m_unAccountInstance == m_unAccountInstance )
&& ( val.m_EAccountType == m_EAccountType ) && ( val.m_EUniverse == m_EUniverse ) );
}
bool operator!=( const CSteamID &val ) const { return !operator==( val ); }
bool operator<( const CSteamID &val ) const { return ConvertToUint64() < val.ConvertToUint64(); }
bool operator>( const CSteamID &val ) const { return ConvertToUint64() > val.ConvertToUint64(); }
// DEBUG function
bool BValidExternalSteamID() const;
private:
// These are defined here to prevent accidental implicit conversion of a u32AccountID to a CSteamID.
// If you get a compiler error about an ambiguous constructor/function then it may be because you're
// passing a 32-bit int to a function that takes a CSteamID. You should explicitly create the SteamID
// using the correct Universe and account Type/Instance values.
CSteamID( uint32 );
CSteamID( int32 );
#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable:4201) // nameless union is nonstandard
// 64 bits total
union
{
struct
{
#endif
uint32 m_unAccountID : 32; // unique account identifier
unsigned int m_unAccountInstance : 20; // dynamic instance ID (used for multiseat type accounts only)
unsigned int m_EAccountType : 4; // type of account - can't show as EAccountType, due to signed / unsigned difference
EUniverse m_EUniverse : 8; // universe this account belongs to
#ifdef _WIN32
};
uint64 m_unAll64Bits;
};
#pragma warning(pop) // no more anonymous unions until next time
#endif
};
const int k_unSteamAccountIDMask = 0xFFFFFFFF;
const int k_unSteamAccountInstanceMask = 0x000FFFFF;
// Special flags for Chat accounts - they go in the top 8 bits
// of the steam ID's "instance", leaving 12 for the actual instances
enum EChatSteamIDInstanceFlags
{
k_EChatAccountInstanceMask = 0x00000FFF, // top 8 bits are flags
k_EChatInstanceFlagClan = ( k_unSteamAccountInstanceMask + 1 ) >> 1, // top bit
k_EChatInstanceFlagLobby = ( k_unSteamAccountInstanceMask + 1 ) >> 2, // next one down, etc
// Max of 8 flags
};
// generic invalid CSteamID
const CSteamID k_steamIDNil;
// This steamID comes from a user game connection to an out of date GS that hasnt implemented the protocol
// to provide its steamID
const CSteamID k_steamIDOutofDateGS( 0, 0, k_EUniverseInvalid, k_EAccountTypeInvalid );
// This steamID comes from a user game connection to an sv_lan GS
const CSteamID k_steamIDLanModeGS( 0, 0, k_EUniversePublic, k_EAccountTypeInvalid );
// This steamID can come from a user game connection to a GS that has just booted but hasnt yet even initialized
// its steam3 component and started logging on.
const CSteamID k_steamIDNotInitYetGS( 1, 0, k_EUniverseInvalid, k_EAccountTypeInvalid );
#ifdef STEAM
// Returns the matching chat steamID, with the default instance of 0
// If the steamID passed in is already of type k_EAccountTypeChat it will be returned with the same instance
CSteamID ChatIDFromSteamID( CSteamID &steamID );
// Returns the matching clan steamID, with the default instance of 0
// If the steamID passed in is already of type k_EAccountTypeClan it will be returned with the same instance
CSteamID ClanIDFromSteamID( CSteamID &steamID );
// Asserts steamID type before conversion
CSteamID ChatIDFromClanID( CSteamID &steamIDClan );
// Asserts steamID type before conversion
CSteamID ClanIDFromChatID( CSteamID &steamIDChat );
#endif // _STEAM
//-----------------------------------------------------------------------------
// Purpose: encapsulates an appID/modID pair
//-----------------------------------------------------------------------------
class CGameID
{
public:
CGameID()
{
m_ulGameID = 0;
}
explicit CGameID( uint64 ulGameID )
{
m_ulGameID = ulGameID;
}
explicit CGameID( int32 nAppID )
{
m_ulGameID = 0;
m_gameID.m_nAppID = nAppID;
}
explicit CGameID( uint32 nAppID )
{
m_ulGameID = 0;
m_gameID.m_nAppID = nAppID;
}
CGameID( uint32 nAppID, uint32 nModID )
{
m_ulGameID = 0;
m_gameID.m_nAppID = nAppID;
m_gameID.m_nModID = nModID;
m_gameID.m_nType = k_EGameIDTypeGameMod;
}
// Hidden functions used only by Steam
explicit CGameID( const char *pchGameID );
char * Render() const; // renders this Game ID to string
static char * Render( uint64 ulGameID ); // static method to render a uint64 representation of a Game ID to a string
// must include checksum_crc.h first to get this functionality
#if defined( CHECKSUM_CRC_H )
CGameID( uint32 nAppID, const char *pchModPath )
{
m_ulGameID = 0;
m_gameID.m_nAppID = nAppID;
m_gameID.m_nType = k_EGameIDTypeGameMod;
char rgchModDir[MAX_PATH];
Q_FileBase( pchModPath, rgchModDir, sizeof( rgchModDir ) );
CRC32_t crc32;
CRC32_Init( &crc32 );
CRC32_ProcessBuffer( &crc32, rgchModDir, Q_strlen( rgchModDir ) );
CRC32_Final( &crc32 );
// set the high-bit on the mod-id
// reduces crc32 to 31bits, but lets us use the modID as a guaranteed unique
// replacement for appID's
m_gameID.m_nModID = crc32 | (0x80000000);
}
CGameID( const char *pchExePath, const char *pchAppName )
{
m_ulGameID = 0;
m_gameID.m_nAppID = 0;
m_gameID.m_nType = k_EGameIDTypeShortcut;
CRC32_t crc32;
CRC32_Init( &crc32 );
CRC32_ProcessBuffer( &crc32, pchExePath, Q_strlen( pchExePath ) );
CRC32_ProcessBuffer( &crc32, pchAppName, Q_strlen( pchAppName ) );
CRC32_Final( &crc32 );
// set the high-bit on the mod-id
// reduces crc32 to 31bits, but lets us use the modID as a guaranteed unique
// replacement for appID's
m_gameID.m_nModID = crc32 | (0x80000000);
}
#endif
void SetAsShortcut()
{
m_gameID.m_nAppID = 0;
m_gameID.m_nType = k_EGameIDTypeShortcut;
}
void SetAsP2PFile()
{
m_gameID.m_nAppID = 0;
m_gameID.m_nType = k_EGameIDTypeP2P;
}
uint64 ToUint64() const
{
return m_ulGameID;
}
uint64 *GetUint64Ptr()
{
return &m_ulGameID;
}
bool IsMod() const
{
return ( m_gameID.m_nType == k_EGameIDTypeGameMod );
}
bool IsShortcut() const
{
return ( m_gameID.m_nType == k_EGameIDTypeShortcut );
}
bool IsP2PFile() const
{
return ( m_gameID.m_nType == k_EGameIDTypeP2P );
}
bool IsSteamApp() const
{
return ( m_gameID.m_nType == k_EGameIDTypeApp );
}
uint32 ModID() const
{
return m_gameID.m_nModID;
}
uint32 AppID() const
{
return m_gameID.m_nAppID;
}
bool operator == ( const CGameID &rhs ) const
{
return m_ulGameID == rhs.m_ulGameID;
}
bool operator != ( const CGameID &rhs ) const
{
return !(*this == rhs);
}
bool operator < ( const CGameID &rhs ) const
{
return ( m_ulGameID < rhs.m_ulGameID );
}
bool IsValid() const
{
return ( m_ulGameID != 0 );
}
void Reset()
{
m_ulGameID = 0;
}
private:
enum EGameIDType
{
k_EGameIDTypeApp = 0,
k_EGameIDTypeGameMod = 1,
k_EGameIDTypeShortcut = 2,
k_EGameIDTypeP2P = 3,
};
struct GameID_t
{
unsigned int m_nAppID : 24;
unsigned int m_nType : 8;
unsigned int m_nModID : 32;
};
union
{
uint64 m_ulGameID;
GameID_t m_gameID;
};
};
#pragma pack( pop )
const int k_cchGameExtraInfoMax = 64;
// Max number of credit cards stored for one account
const int k_nMaxNumCardsPerAccount = 1;
//-----------------------------------------------------------------------------
// Constants used for query ports.
//-----------------------------------------------------------------------------
#define QUERY_PORT_NOT_INITIALIZED 0xFFFF // We haven't asked the GS for this query port's actual value yet.
#define QUERY_PORT_ERROR 0xFFFE // We were unable to get the query port for this server.
#endif // STEAMCLIENTPUBLIC_H
+85
View File
@@ -0,0 +1,85 @@
//========= Copyright © 1996-2008, Valve LLC, All rights reserved. ============
//
// Purpose:
//
//=============================================================================
#ifndef STEAMTYPES_H
#define STEAMTYPES_H
#ifdef _WIN32
#pragma once
#endif
// Steam-specific types. Defined here so this header file can be included in other code bases.
#ifndef WCHARTYPES_H
typedef unsigned char uint8;
#endif
#if defined(__x86_64__) || defined(_WIN64)
#define X64BITS
#endif
typedef unsigned char uint8;
typedef signed char int8;
#if defined( _WIN32 )
typedef __int16 int16;
typedef unsigned __int16 uint16;
typedef __int32 int32;
typedef unsigned __int32 uint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
#ifdef X64BITS
typedef __int64 intp; // intp is an integer that can accomodate a pointer
typedef unsigned __int64 uintp; // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *)
#else
typedef __int32 intp;
typedef unsigned __int32 uintp;
#endif
#else // _WIN32
typedef short int16;
typedef unsigned short uint16;
typedef int int32;
typedef unsigned int uint32;
typedef long long int64;
typedef unsigned long long uint64;
#ifdef X64BITS
typedef long long intp;
typedef unsigned long long uintp;
#else
typedef int intp;
typedef unsigned int uintp;
#endif
#endif // else _WIN32
const int k_cubDigestSize = 20; // CryptoPP::SHA::DIGESTSIZE
const int k_cubSaltSize = 8;
typedef uint8 SHADigest_t[ k_cubDigestSize ];
typedef uint8 Salt_t[ k_cubSaltSize ];
typedef uint64 GID_t; // globally unique identifier
// this is baked into client messages and interfaces as an int,
// make sure we never break this.
typedef uint32 PackageId_t;
const PackageId_t k_uPackageIdInvalid = 0xFFFFFFFF;
// this is baked into client messages and interfaces as an int,
// make sure we never break this.
typedef uint32 AppId_t;
const AppId_t k_uAppIdInvalid = 0xFFFFFFFF;
// RTime32
// We use this 32 bit time representing real world time.
// It offers 1 second resolution beginning on January 1, 1970 (Unix time)
typedef uint32 RTime32;
#endif // STEAMTYPES_H
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+29
View File
@@ -0,0 +1,29 @@
:Base ContentTool.hlp
1 Getting Started
2 What is ContentTool=IDH_ABOUT_CONTENTTOOL
2 ContentTool Components=IDH_CONTENTTOOL_COMPONENTS
2 Overview of Steam Publishing=IDH_CONTENTTOOL_OVERVIEW
1 Step-by-Step Procedures
2 Creating a New Depot=IDH_CREATE_NEW_DEPOT
2 Adding Files to a Depot=IDH_ADDING_FILES
2 Moving Files in the Depot=IDH_MOVING_FILES
2 Deleting Files in the Depot=IDH_DELETING_FILES
2 Assigning Attributes to Files=IDH_ASSIGNING_ATTRIBUTES
2 Building the Depot=IDH_BUILING_DEPOT
2 Adding New Versions=IDH_ADDING_NEW_VERSIONS
2 Modifying Old Versions=IDH_MOD_OLD_VERSIONS
2 Publishing your Depot=IDH_EDITCONTENT
1 ContentTool Reference
2 Menus
3 File menu=menu_file
3 Edit menu=menu_edit
3 View menu=menu_view
3 Project menu=menu_project
3 Build menu=menu_build
3 Reslist menu=menu_reslist
3 Help menu=menu_help
2 Scripting
3 Scripting overview=IDH_SCRIPT_OVERVIEW
3 Creating script files=IDH_SCRIPT_FILE
3 Script commands=IDH_SCRIPT_CMDS
3 Running scripts=IDH_SCRIPT_RUN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
[autorun]
OPEN=SETUP.EXE
ICON=ICON.ICO
Binary file not shown.
+26
View File
@@ -0,0 +1,26 @@
{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\froman\fcharset0 Times;}{\f1\froman\fcharset0 Times New Roman;}{\f2\fswiss\fcharset0 Arial;}}
{\colortbl ;\red0\green0\blue0;}
{\*\generator Msftedit 5.41.15.1507;}\viewkind4\uc1\pard\nowidctlpar\fi720\qc\b\f0\fs20 YOU SHOULD CAREFULLY READ THE ENTIRE FOLLOWING LICENSE AGREEMENT BEFORE INSTALLING THIS SOFTWARE PROGRAM. THIS AGREEMENT CONTAINS IMPORTANT TERMS THAT AFFECT YOUR LEGAL RIGHTS. BY INSTALLING THE SOFTWARE PROGRAM, YOU AGREE TO BE BOUND BY THE TERMS OF THIS AGREEMENT. IF YOU DO NOT AGREE TO THE TERMS OF THIS AGREEMENT, PLEASE DO NOT INSTALL THIS SOFTWARE PROGRAM.\par
\par
\pard\nowidctlpar\sa120\qj\tx360\tx720\b0 The software application(s) (the \ldblquote\ul Program\ulnone\rdblquote ), and any and all copies of the Program are the copyrighted work of Valve Corporation (\ldblquote\ul Valve\ulnone\rdblquote ) or its suppliers. All rights reserved, except as expressly stated herein. The Program is provided solely for installation by end users according to the terms of this License Agreement. All use of the Program is governed by the terms of the Steam Agreement as described below. Any use, reproduction or redistribution of the Program not in accordance with the terms of the License Agreement and the Steam Agreement is expressly prohibited.\par
\pard\nowidctlpar\qc\ul\b\f1 LICENSE AGREEMENT\par
\pard\nowidctlpar\par
\pard\nowidctlpar\qj\tx360\ulnone\b0\tab 1. \ul Limited Installation License\ulnone . \par
\par
\pard\nowidctlpar\fi720\qj\tx360 A. Valve hereby grants, and by installing the Program you thereby accept, a limited, non-exclusive license and right to install one (1) copy of the Program on a computer. In order to use the Program you will have to obtain an account with the Steam service and accept the terms of the \f0 Steam subscriber agreement (\ldblquote\ul Steam Agreement\ulnone\rdblquote )\f1 . \f0 By installing the Program, you agree that your future use of the Program will be subject to the terms of the Steam Agreement. A copy of the Steam Agreement is available at \ul www.steampowered.com/agreement.\ulnone \f1 The Steam Agreement will be displayed to you when you obtain an account with the Steam service. The Program is licensed, not sold. Your license confers no title or ownership in the Program or copies thereof.\par
\pard\nowidctlpar\qj\tx360\par
\pard\nowidctlpar\fi720 B. \f0 You may not, in whole or in part: copy, photocopy, reproduce, translate, reverse engineer\cf1 (with the exception of specific circumstances where such act is permitted by law)\cf0 , derive source code, modify, disassemble, decompile, or create derivative works based on the Program; remove any proprietary notices or labels on the Program; or attempt in any manner to circumvent any security measures designed to control access to the Program. The Program is licensed to you as a single product. Its component parts may not be separated for use on more than one computer. You may not sell, grant a security interest in or transfer reproductions of the Program to other parties in any way, nor to rent, lease or license the Program to others without the prior written consent of Valve.\f1\par
\pard\nowidctlpar\sa120\qj\tx360\tx720\f0\tab\par
\tab 2. \ul Ownership\ulnone . All title, ownership rights and intellectual property rights in and to the Program and any and all copies thereof (including but not limited to any titles, computer code, themes, objects, characters, character names, stories, dialog, catch phrases, locations, concepts, artwork, animations, sounds, musical compositions, audio-visual effects, methods of operation, moral rights, any related documentation, and \ldblquote applets\rdblquote incorporated into the Program) are owned by Valve or its licensors. The Program is protected by the copyright laws of the United States, international copyright treaties and conventions and other laws. All rights are reserved. The Program contains certain licensed materials and Valve\rquote s licensors may protect their rights in the event of any violation of this Agreement.\par
\tab 3. \ul Termination\ulnone . This License Agreement is effective until terminated. You may terminate the License Agreement at any time by destroying the Program. Valve may, at its discretion, terminate this License Agreement in the event that you fail to comply with the terms and conditions contained herein. This License Agreement shall automatically terminate in the event that you fail to comply with the terms and conditions contained herein. In such event, you must immediately destroy the Program. The provisions of Sections 2, 3, and 5-8 will survive any termination of the Agreement. \par
\tab 4. \ul Export Controls\ulnone . The Program may not be re-exported, downloaded or otherwise exported into (or to a national or resident of) any country to which the U.S. has embargoed goods, or to anyone on the U.S. Treasury Department\rquote s list of Specially Designated Nationals or the U.S. Commerce Department\rquote s Table of Denial Orders. By installing the Program, you are agreeing to the foregoing and you are representing and warranting that you are not located in, under the control of, or a national or resident of any such country or on any such list.\par
\pard\nowidctlpar\fi360\qj\tx8100\f1 5. \ul Limited Warranty\ulnone . The entire risk arising out of use or performance of the Program and any printed material(s) remains with the User.\f2 \f1 EXCEPT AS PROVIDED ABOVE, \caps The Program and ANY PRINTED MATERIAL(s) are provided "as is" without warranty of any kind, either express or implied, including, without limitation, the implied warranties of merchantability, fitness for a particular purpose, or noninfringement. \caps0 ANY WARRANTY AGAINST INFRINGEMENT THAT MAY BE PROVIDED IN SECTION 2-312(3) OF THE UNIFORM COMMERCIAL CODE AND/OR IN ANY OTHER COMPARABLE STATE STATUTE IS EXPRESSLY DISCLAIMED. Some states/jurisdictions do not allow the exclusion or limitation of implied warranties, so the above limitations may not apply to you.\par
\pard\nowidctlpar\qj\tx360\tx720\f0\fs18\par
\pard\nowidctlpar\qj\tx360\f1\tab 6. \ul\fs20 Limitation of Liability\ulnone . VALVE, ITS SUPPLIERS AND DISTRIBUTORS SHALL NOT BE LIABLE IN ANY WAY FOR LOSS OR DAMAGE OF ANY KIND RESULTING FROM THE USE OF THE PROGRAM INCLUDING, BUT NOT LIMITED TO, LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES. ANY WARRANTY AGAINST INFRINGEMENT THAT MAY BE PROVIDED IN SECTION 2-312(3) OF THE UNIFORM COMMERCIAL CODE AND/OR IN ANY OTHER COMPARABLE STATE STATUTE IS EXPRESSLY DISCLAIMED. \caps Valve CANNOT AND WILL NOT BE RESPONSIBLE FOR ANY SOFTWARE OR HARDWARE FAILURES OR ANY OTHER EVENT WHICH MAY RESULT IN A LOSS OF DATA OR DISRUPTION OF SERVICE. \caps0 Some states/jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so the above limitations may not apply. \par
\pard\nowidctlpar\qj\par
\pard\nowidctlpar\sa120\qj\tx360\tab 7. \ul Equitable Remedies\ulnone . You hereby agree that Valve would be irreparably damaged if the terms of this License Agreement were not specifically enforced, and therefore you agree that Valve shall be entitled to appropriate equitable remedies with respect to breaches of this License Agreement, in addition to such other remedies as Valve may otherwise have available to it under applicable laws. In the event any litigation is brought by either party in connection with this License Agreement, the prevailing party in such litigation shall be entitled to recover from the other party all the costs, attorneys\rquote fees and other expenses incurred by such prevailing party in the litigation.\par
\tab 8. \ul Miscellaneous\ulnone .\cf1 The terms of this paragraph do not apply to European Union consumers in the sense of Art. 5 of the Convention on the Law Applicable to Contractual Obligations opened for signature in Rome on 19 June 1980 (Rome Convention, 80/934/EEC) and national legislation based thereon.\cf0 You agree that this Agreement shall be deemed to have been made and executed in the State of Washington, and any dispute arising hereunder shall be resolved in accordance with the law of Washington. You agree that any claim asserted in any legal proceeding by you against Valve shall only be commenced and maintained in any state or federal court located in King County, Washington, and you agree to submit to the exclusive jurisdiction of those courts. In any dispute arising under this Agreement, the prevailing party will be entitled to attorneys' fees and expenses. This License Agreement may be amended, altered or modified only by an instrument in writing, specifying such amendment, alteration or modification, executed by both you and Valve. In the event that any provision of this License Agreement shall be held by a court or other tribunal of competent jurisdiction to be unenforceable, such provision will be enforced to the maximum extent permissible and the remaining portions of this License Agreement shall remain in full force and effect. This License Agreement and the Steam Agreement constitute and contain the entire agreement between the parties with respect to the subject matter hereof and supersede any prior oral or written agreements.\par
You hereby acknowledge that you have read and understand the foregoing License Agreement and agree that the action of installing the Program is an acknowledgment of your agreement to be bound by the terms and conditions of the License Agreement contained herein.\par
\par
}
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 900 KiB

@@ -0,0 +1,32 @@
// Config data, do not localize
"Game" "Example Game" // product name
"Image" "setup.bmp" // backgound image BMP 640x480
"FontName" "Impact" // menu font name
"FontHeight" "24" // menu font height
"MenuPos" "200 324" // postion of menu X Y
"MenuStyle" "1" // 0 = align left, 1 = center, 2 = right
"ColorDefault" "255 255 255" // default button color RGB
"ColorHover" "250 180 60" // button hover color RGB
"ColorDown" "0 0 0" // button click color RGB
"AppID" "16400" // primary appID
"Language" "english"
"MSIFile" "SteamInstall.msi"
"URL" "http://support.steampowered.com/"
// UI text, localize 2nd string. s% is a placeholder for game name
"InstallGame" "Install %s"
"Support" "Technical Support"
"Exit" "Exit"
"Continue" "Continue"
"Cancel" "Cancel"
"Back" "Back"
"Play" "Play %s"
"Install" "Install"
"Reinstall" "Reinstall"
"Uninstall" "Uninstall"
"Steam" "%s uses Steam to stay up to date, delivering updates and new content straight to your desktop."
"Click" "Click Continue to log in or create an Account."
"EulaTitle" "License Agreement"
"AcceptEula" "I accept the terms in the license agreement"
"DenyEula" "I do not accept the terms in the license agreement"
Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

+10
View File
@@ -0,0 +1,10 @@
[Ident]
Version=1.0.0.0
PatchVersion=1.0.0.0
Language=English
ShortTitle=EXAMPLE
Title=Example Game
GameName=Game Example
RequiredSize=1800000
RequiredString=1.8
+2
View File
@@ -0,0 +1,2 @@
steam.exe -login <account> <password> -language english -build_install sku_project_example.txt -dest <path>
@type build_log.txt
+6
View File
@@ -0,0 +1,6 @@
"sku"
{
"subscriptionID" "710"
"appID" "200"
"disk_size_mb" "4700"
}