Initial commit: ROW Client source code

Game client codebase including:
- CharacterActionControl: Character and creature management
- GlobalScript: Network, items, skills, quests, utilities
- RYLClient: Main client application with GUI and event handlers
- Engine: 3D rendering engine (RYLGL)
- MemoryManager: Custom memory allocation
- Library: Third-party dependencies (DirectX, boost, etc.)
- Tools: Development utilities

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-29 16:24:34 +09:00
commit e067522598
5135 changed files with 1745744 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "ChatPeer"=.\ChatPeer.dsp - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -0,0 +1,378 @@
# Microsoft Developer Studio Generated NMAKE File, Based on ChatPeer.dsp
!IF "$(CFG)" == ""
CFG=ChatPeer - Win32 Debug Unicode
!MESSAGE No configuration specified. Defaulting to ChatPeer - Win32 Debug Unicode.
!ENDIF
!IF "$(CFG)" != "ChatPeer - Win32 Release" && "$(CFG)" != "ChatPeer - Win32 Debug" && "$(CFG)" != "ChatPeer - Win32 Debug Unicode" && "$(CFG)" != "ChatPeer - Win32 Release Unicode"
!MESSAGE Invalid configuration "$(CFG)" specified.
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ChatPeer.mak" CFG="ChatPeer - Win32 Debug Unicode"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ChatPeer - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "ChatPeer - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE "ChatPeer - Win32 Debug Unicode" (based on "Win32 (x86) Application")
!MESSAGE "ChatPeer - Win32 Release Unicode" (based on "Win32 (x86) Application")
!MESSAGE
!ERROR An invalid configuration is specified.
!ENDIF
!IF "$(OS)" == "Windows_NT"
NULL=
!ELSE
NULL=nul
!ENDIF
!IF "$(CFG)" == "ChatPeer - Win32 Release"
OUTDIR=.\Release
INTDIR=.\Release
# Begin Custom Macros
OutDir=.\Release
# End Custom Macros
ALL : "$(OUTDIR)\ChatPeer.exe"
CLEAN :
-@erase "$(INTDIR)\ChatPeer.obj"
-@erase "$(INTDIR)\ChatPeer.res"
-@erase "$(INTDIR)\dxutil.obj"
-@erase "$(INTDIR)\NetConnect.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(OUTDIR)\ChatPeer.exe"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP=cl.exe
CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "." /I "..\..\common\include" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /D "_WIN32_DCOM" /Fp"$(INTDIR)\ChatPeer.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.c{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
MTL=midl.exe
MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
RSC=rc.exe
RSC_PROJ=/l 0x409 /fo"$(INTDIR)\ChatPeer.res" /d "NDEBUG"
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\ChatPeer.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=dplay.lib dxguid.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib odbc32.lib odbccp32.lib dxerr8.lib winmm.lib kernel32.lib user32.lib ole32.lib uuid.lib /nologo /subsystem:windows /incremental:no /pdb:"$(OUTDIR)\ChatPeer.pdb" /machine:I386 /out:"$(OUTDIR)\ChatPeer.exe" /stack:0x10000,0x10000
LINK32_OBJS= \
"$(INTDIR)\ChatPeer.obj" \
"$(INTDIR)\dxutil.obj" \
"$(INTDIR)\NetConnect.obj" \
"$(INTDIR)\ChatPeer.res"
"$(OUTDIR)\ChatPeer.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "ChatPeer - Win32 Debug"
OUTDIR=.\Debug
INTDIR=.\Debug
# Begin Custom Macros
OutDir=.\Debug
# End Custom Macros
ALL : "$(OUTDIR)\ChatPeer.exe"
CLEAN :
-@erase "$(INTDIR)\ChatPeer.obj"
-@erase "$(INTDIR)\ChatPeer.res"
-@erase "$(INTDIR)\dxutil.obj"
-@erase "$(INTDIR)\NetConnect.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\vc60.pdb"
-@erase "$(OUTDIR)\ChatPeer.exe"
-@erase "$(OUTDIR)\ChatPeer.ilk"
-@erase "$(OUTDIR)\ChatPeer.pdb"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP=cl.exe
CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\common\include" /D "_WINDOWS" /D "_DEBUG" /D "WIN32" /D "_WIN32_DCOM" /Fp"$(INTDIR)\ChatPeer.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.c{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
MTL=midl.exe
MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
RSC=rc.exe
RSC_PROJ=/l 0x409 /fo"$(INTDIR)\ChatPeer.res" /d "_DEBUG"
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\ChatPeer.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=dplay.lib dxguid.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib odbc32.lib odbccp32.lib dxerr8.lib winmm.lib kernel32.lib user32.lib ole32.lib uuid.lib /nologo /subsystem:windows /incremental:yes /pdb:"$(OUTDIR)\ChatPeer.pdb" /debug /machine:I386 /nodefaultlib:"LIBC" /out:"$(OUTDIR)\ChatPeer.exe" /pdbtype:sept /stack:0x10000,0x10000
LINK32_OBJS= \
"$(INTDIR)\ChatPeer.obj" \
"$(INTDIR)\dxutil.obj" \
"$(INTDIR)\NetConnect.obj" \
"$(INTDIR)\ChatPeer.res"
"$(OUTDIR)\ChatPeer.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "ChatPeer - Win32 Debug Unicode"
OUTDIR=.\Win32_Debug_Unicode
INTDIR=.\Win32_Debug_Unicode
# Begin Custom Macros
OutDir=.\Win32_Debug_Unicode
# End Custom Macros
ALL : "$(OUTDIR)\ChatPeer.exe"
CLEAN :
-@erase "$(INTDIR)\ChatPeer.obj"
-@erase "$(INTDIR)\ChatPeer.res"
-@erase "$(INTDIR)\dxutil.obj"
-@erase "$(INTDIR)\NetConnect.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(INTDIR)\vc60.pdb"
-@erase "$(OUTDIR)\ChatPeer.exe"
-@erase "$(OUTDIR)\ChatPeer.ilk"
-@erase "$(OUTDIR)\ChatPeer.pdb"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP=cl.exe
CPP_PROJ=/nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\common\include" /D "_DEBUG" /D "_WINDOWS" /D "WIN32" /D "_WIN32_DCOM" /D "UNICODE" /D "_UNICODE" /Fp"$(INTDIR)\ChatPeer.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.c{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
MTL=midl.exe
MTL_PROJ=/nologo /D "_DEBUG" /mktyplib203 /win32
RSC=rc.exe
RSC_PROJ=/l 0x409 /fo"$(INTDIR)\ChatPeer.res" /d "_DEBUG"
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\ChatPeer.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=dplay.lib dxguid.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib odbc32.lib odbccp32.lib dxerr8.lib winmm.lib kernel32.lib user32.lib ole32.lib uuid.lib /nologo /subsystem:windows /incremental:yes /pdb:"$(OUTDIR)\ChatPeer.pdb" /debug /machine:I386 /nodefaultlib:"LIBC" /out:"$(OUTDIR)\ChatPeer.exe" /pdbtype:sept /stack:0x10000,0x10000
LINK32_OBJS= \
"$(INTDIR)\ChatPeer.obj" \
"$(INTDIR)\dxutil.obj" \
"$(INTDIR)\NetConnect.obj" \
"$(INTDIR)\ChatPeer.res"
"$(OUTDIR)\ChatPeer.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ELSEIF "$(CFG)" == "ChatPeer - Win32 Release Unicode"
OUTDIR=.\Win32_Release_Unicode
INTDIR=.\Win32_Release_Unicode
# Begin Custom Macros
OutDir=.\Win32_Release_Unicode
# End Custom Macros
ALL : "$(OUTDIR)\ChatPeer.exe"
CLEAN :
-@erase "$(INTDIR)\ChatPeer.obj"
-@erase "$(INTDIR)\ChatPeer.res"
-@erase "$(INTDIR)\dxutil.obj"
-@erase "$(INTDIR)\NetConnect.obj"
-@erase "$(INTDIR)\vc60.idb"
-@erase "$(OUTDIR)\ChatPeer.exe"
"$(OUTDIR)" :
if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
CPP=cl.exe
CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "." /I "..\..\common\include" /D "NDEBUG" /D "_MBCS" /D "_WINDOWS" /D "WIN32" /D "_WIN32_DCOM" /D "UNICODE" /D "_UNICODE" /Fp"$(INTDIR)\ChatPeer.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
.c{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.obj::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.c{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cpp{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
.cxx{$(INTDIR)}.sbr::
$(CPP) @<<
$(CPP_PROJ) $<
<<
MTL=midl.exe
MTL_PROJ=/nologo /D "NDEBUG" /mktyplib203 /win32
RSC=rc.exe
RSC_PROJ=/l 0x409 /fo"$(INTDIR)\ChatPeer.res" /d "NDEBUG"
BSC32=bscmake.exe
BSC32_FLAGS=/nologo /o"$(OUTDIR)\ChatPeer.bsc"
BSC32_SBRS= \
LINK32=link.exe
LINK32_FLAGS=dplay.lib dxguid.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib odbc32.lib odbccp32.lib dxerr8.lib winmm.lib kernel32.lib user32.lib ole32.lib uuid.lib /nologo /subsystem:windows /incremental:no /pdb:"$(OUTDIR)\ChatPeer.pdb" /machine:I386 /out:"$(OUTDIR)\ChatPeer.exe" /stack:0x10000,0x10000
LINK32_OBJS= \
"$(INTDIR)\ChatPeer.obj" \
"$(INTDIR)\dxutil.obj" \
"$(INTDIR)\NetConnect.obj" \
"$(INTDIR)\ChatPeer.res"
"$(OUTDIR)\ChatPeer.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
$(LINK32) @<<
$(LINK32_FLAGS) $(LINK32_OBJS)
<<
!ENDIF
!IF "$(NO_EXTERNAL_DEPS)" != "1"
!IF EXISTS("ChatPeer.dep")
!INCLUDE "ChatPeer.dep"
!ELSE
!MESSAGE Warning: cannot find "ChatPeer.dep"
!ENDIF
!ENDIF
!IF "$(CFG)" == "ChatPeer - Win32 Release" || "$(CFG)" == "ChatPeer - Win32 Debug" || "$(CFG)" == "ChatPeer - Win32 Debug Unicode" || "$(CFG)" == "ChatPeer - Win32 Release Unicode"
SOURCE=.\ChatPeer.cpp
"$(INTDIR)\ChatPeer.obj" : $(SOURCE) "$(INTDIR)"
SOURCE=.\ChatPeer.rc
"$(INTDIR)\ChatPeer.res" : $(SOURCE) "$(INTDIR)"
$(RSC) $(RSC_PROJ) $(SOURCE)
SOURCE=..\..\common\src\dxutil.cpp
"$(INTDIR)\dxutil.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
SOURCE=..\..\common\src\NetConnect.cpp
"$(INTDIR)\NetConnect.obj" : $(SOURCE) "$(INTDIR)"
$(CPP) $(CPP_PROJ) $(SOURCE)
!ENDIF

View File

@@ -0,0 +1,772 @@
//----------------------------------------------------------------------------
// File: ChatPeer.cpp
//
// Desc: The main game file for the ChatPeer sample. It connects
// players together with two dialog boxes to prompt users on the
// connection settings to join or create a session. After the user
// connects to a sesssion, the sample displays a multiplayer stage.
//
// After a new game has started the sample begins a very simplistic
// chat session where users can send text to each other.
//
// Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
//-----------------------------------------------------------------------------
#define STRICT
#include <windows.h>
#include <basetsd.h>
#include <richedit.h>
#include <dplay8.h>
#include <dplobby8.h>
#include <dxerr8.h>
#include "NetConnect.h"
#include "DXUtil.h"
#include "resource.h"
//-----------------------------------------------------------------------------
// Player context locking defines
//-----------------------------------------------------------------------------
CRITICAL_SECTION g_csPlayerContext;
#define PLAYER_LOCK() EnterCriticalSection( &g_csPlayerContext );
#define PLAYER_ADDREF( pPlayerInfo ) if( pPlayerInfo ) pPlayerInfo->lRefCount++;
#define PLAYER_RELEASE( pPlayerInfo ) if( pPlayerInfo ) { pPlayerInfo->lRefCount--; if( pPlayerInfo->lRefCount <= 0 ) SAFE_DELETE( pPlayerInfo ); } pPlayerInfo = NULL;
#define PLAYER_UNLOCK() LeaveCriticalSection( &g_csPlayerContext );
//-----------------------------------------------------------------------------
// Defines, and constants
//-----------------------------------------------------------------------------
#define DPLAY_SAMPLE_KEY TEXT("Software\\Microsoft\\DirectX DirectPlay Samples")
#define MAX_PLAYER_NAME 14
#define MAX_CHAT_STRINGS 50
#define MAX_CHAT_STRING_LENGTH 508
#define WM_APP_UPDATE_STATS (WM_APP + 0)
#define WM_APP_CHAT (WM_APP + 1)
// This GUID allows DirectPlay to find other instances of the same game on
// the network. So it must be unique for every game, and the same for
// every instance of that game. // {876A3036-FFD7-46bc-9209-B42F617B9BE7}
GUID g_guidApp = { 0x876a3036, 0xffd7, 0x46bc, { 0x92, 0x9, 0xb4, 0x2f, 0x61, 0x7b, 0x9b, 0xe7 } };
struct APP_PLAYER_INFO
{
LONG lRefCount; // Ref count so we can cleanup when all threads
// are done w/ this object
DPNID dpnidPlayer; // DPNID of player
TCHAR strPlayerName[MAX_PLAYER_NAME]; // Player name
};
//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
IDirectPlay8Peer* g_pDP = NULL; // DirectPlay peer object
CNetConnectWizard* g_pNetConnectWizard = NULL; // Connection wizard
IDirectPlay8LobbiedApplication* g_pLobbiedApp = NULL; // DirectPlay lobbied app
BOOL g_bWasLobbyLaunched = FALSE; // TRUE if lobby launched
HINSTANCE g_hInst = NULL; // HINST of app
HWND g_hDlg = NULL; // HWND of main dialog
DPNID g_dpnidLocalPlayer = 0; // DPNID of local player
LONG g_lNumberOfActivePlayers = 0; // Number of players currently in game
TCHAR g_strAppName[256] = TEXT("ChatPeer");
HRESULT g_hrDialog; // Exit code for app
TCHAR g_strLocalPlayerName[MAX_PATH]; // Local player name
TCHAR g_strSessionName[MAX_PATH]; // Session name
TCHAR g_strPreferredProvider[MAX_PATH]; // Provider string
//-----------------------------------------------------------------------------
// App specific DirectPlay messages and structures
//-----------------------------------------------------------------------------
#define GAME_MSGID_CHAT 1
// Change compiler pack alignment to be BYTE aligned, and pop the current value
#pragma pack( push, 1 )
struct GAMEMSG_GENERIC
{
BYTE nType;
};
struct GAMEMSG_CHAT : public GAMEMSG_GENERIC
{
TCHAR strChatString[MAX_CHAT_STRING_LENGTH];
};
// Pop the old pack alignment
#pragma pack( pop )
struct APP_QUEUED_DATA
{
GAMEMSG_CHAT* pChatMsg;
DPNHANDLE hBufferHandle;
};
//-----------------------------------------------------------------------------
// Function-prototypes
//-----------------------------------------------------------------------------
HRESULT WINAPI DirectPlayMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer );
HRESULT WINAPI DirectPlayLobbyMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer );
INT_PTR CALLBACK ChatDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
HRESULT InitDirectPlay();
HRESULT OnInitDialog( HWND hDlg );
HRESULT SendChatMessage( HWND hDlg );
//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Entry point for the application. Since we use a simple dialog for
// user interaction we don't need to pump messages.
//-----------------------------------------------------------------------------
INT APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst,
LPSTR pCmdLine, INT nCmdShow )
{
HRESULT hr;
HKEY hDPlaySampleRegKey;
BOOL bConnectSuccess = FALSE;
g_hInst = hInst;
InitializeCriticalSection( &g_csPlayerContext );
// Read persistent state information from registry
RegCreateKeyEx( HKEY_CURRENT_USER, DPLAY_SAMPLE_KEY, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
&hDPlaySampleRegKey, NULL );
DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Player Name"),
g_strLocalPlayerName, MAX_PATH, TEXT("TestPlayer") );
DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Session Name"),
g_strSessionName, MAX_PATH, TEXT("TestGame") );
DXUtil_ReadStringRegKey( hDPlaySampleRegKey, TEXT("Preferred Provider"),
g_strPreferredProvider, MAX_PATH, TEXT("DirectPlay8 TCP/IP Service Provider") );
// Init COM so we can use CoCreateInstance
CoInitializeEx( NULL, COINIT_MULTITHREADED );
// Create helper class
g_pNetConnectWizard = new CNetConnectWizard( hInst, NULL, g_strAppName, &g_guidApp );
if( FAILED( hr = InitDirectPlay() ) )
{
DXTRACE_ERR( TEXT("InitDirectPlay"), hr );
MessageBox( NULL, TEXT("Failed initializing IDirectPlay8Peer. ")
TEXT("The sample will now quit."),
TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
goto LCleanup;
}
// Check if we were launched from a lobby client
if( g_bWasLobbyLaunched && g_pNetConnectWizard->HaveConnectionSettingsFromLobby() )
{
// If were lobby launched then DPL_MSGID_CONNECT has already been
// handled, so we can just tell the wizard to connect to the lobby
// that has sent us a DPL_MSGID_CONNECT msg.
if( FAILED( hr = g_pNetConnectWizard->ConnectUsingLobbySettings() ) )
{
DXTRACE_ERR( TEXT("ConnectUsingLobbySettings"), hr );
MessageBox( NULL, TEXT("Failed to connect using lobby settings. ")
TEXT("The sample will now quit."),
TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
bConnectSuccess = FALSE;
}
else
{
// Read information from g_pNetConnectWizard
_tcscpy( g_strLocalPlayerName, g_pNetConnectWizard->GetPlayerName() );
bConnectSuccess = TRUE;
}
}
else
{
// If not lobby launched, prompt the user about the network
// connection and which session they would like to join or
// if they want to create a new one.
// Setup connection wizard
g_pNetConnectWizard->SetPlayerName( g_strLocalPlayerName );
g_pNetConnectWizard->SetSessionName( g_strSessionName );
g_pNetConnectWizard->SetPreferredProvider( g_strPreferredProvider );
// Do the connection wizard
hr = g_pNetConnectWizard->DoConnectWizard( FALSE );
if( FAILED( hr ) )
{
DXTRACE_ERR( TEXT("DoConnectWizard"), hr );
MessageBox( NULL, TEXT("Multiplayer connect failed. ")
TEXT("The sample will now quit."),
TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
bConnectSuccess = FALSE;
}
else if( hr == NCW_S_QUIT )
{
// The user canceled the Multiplayer connect, so quit
bConnectSuccess = FALSE;
}
else
{
bConnectSuccess = TRUE;
// Read information from g_pNetConnectWizard
_tcscpy( g_strLocalPlayerName, g_pNetConnectWizard->GetPlayerName() );
_tcscpy( g_strSessionName, g_pNetConnectWizard->GetSessionName() );
_tcscpy( g_strPreferredProvider, g_pNetConnectWizard->GetPreferredProvider() );
// Write information to the registry
DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Player Name"), g_strLocalPlayerName );
DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Session Name"), g_strSessionName );
DXUtil_WriteStringRegKey( hDPlaySampleRegKey, TEXT("Preferred Provider"), g_strPreferredProvider );
}
}
if( bConnectSuccess )
{
// App is now connected via DirectPlay, so start the game.
// For this sample, we just start a simple dialog box game.
g_hrDialog = S_OK;
DialogBox( hInst, MAKEINTRESOURCE(IDD_MAIN_GAME), NULL, (DLGPROC) ChatDlgProc );
if( FAILED( g_hrDialog ) )
{
if( g_hrDialog == DPNERR_CONNECTIONLOST )
{
MessageBox( NULL, TEXT("The DirectPlay session was lost. ")
TEXT("The sample will now quit."),
TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
}
else
{
DXTRACE_ERR( TEXT("DialogBox"), g_hrDialog );
MessageBox( NULL, TEXT("An error occured during the game. ")
TEXT("The sample will now quit."),
TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
}
}
}
LCleanup:
// Cleanup DirectPlay and helper classes
g_pNetConnectWizard->Shutdown();
if( g_pDP )
{
g_pDP->Close(0);
SAFE_RELEASE( g_pDP );
}
if( g_pLobbiedApp )
{
g_pLobbiedApp->Close( 0 );
SAFE_RELEASE( g_pLobbiedApp );
}
// Don't delete the wizard until we know that
// DirectPlay is out of its message handlers.
// This will be true after Close() has been called.
SAFE_DELETE( g_pNetConnectWizard );
RegCloseKey( hDPlaySampleRegKey );
DeleteCriticalSection( &g_csPlayerContext );
CoUninitialize();
return TRUE;
}
//-----------------------------------------------------------------------------
// Name: InitDirectPlay()
// Desc:
//-----------------------------------------------------------------------------
HRESULT InitDirectPlay()
{
DPNHANDLE hLobbyLaunchedConnection = NULL;
HRESULT hr;
// Create IDirectPlay8Peer
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Peer, NULL,
CLSCTX_INPROC_SERVER,
IID_IDirectPlay8Peer,
(LPVOID*) &g_pDP ) ) )
return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
// Create IDirectPlay8LobbiedApplication
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8LobbiedApplication, NULL,
CLSCTX_INPROC_SERVER,
IID_IDirectPlay8LobbiedApplication,
(LPVOID*) &g_pLobbiedApp ) ) )
return DXTRACE_ERR( TEXT("CoCreateInstance"), hr );
// Init the helper class, now that g_pDP and g_pLobbiedApp are valid
g_pNetConnectWizard->Init( g_pDP, g_pLobbiedApp );
// Init IDirectPlay8Peer
if( FAILED( hr = g_pDP->Initialize( NULL, DirectPlayMessageHandler, 0 ) ) )
return DXTRACE_ERR( TEXT("Initialize"), hr );
// Init IDirectPlay8LobbiedApplication. Before this Initialize() returns
// a DPL_MSGID_CONNECT msg may come in to the DirectPlayLobbyMessageHandler
// so be prepared ahead of time.
if( FAILED( hr = g_pLobbiedApp->Initialize( NULL, DirectPlayLobbyMessageHandler,
&hLobbyLaunchedConnection, 0 ) ) )
return DXTRACE_ERR( TEXT("Initialize"), hr );
// IDirectPlay8LobbiedApplication::Initialize returns a handle to a connnection
// if we have been lobby launced. Initialize is guanteeded to return after
// the DPL_MSGID_CONNECT msg has been processed. So unless a we are expected
// multiple lobby connections, we do not need to remember the lobby connection
// handle since it will be recorded upon the DPL_MSGID_CONNECT msg.
g_bWasLobbyLaunched = ( hLobbyLaunchedConnection != NULL );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: ChatDlgProc()
// Desc: Handles dialog messages
//-----------------------------------------------------------------------------
INT_PTR CALLBACK ChatDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_INITDIALOG:
{
g_hDlg = hDlg;
if( FAILED( g_hrDialog = OnInitDialog( hDlg ) ) )
{
DXTRACE_ERR( TEXT("OnInitDialog"), g_hrDialog );
EndDialog( hDlg, 0 );
}
break;
}
case WM_APP_UPDATE_STATS:
{
// Update the number of players in the game
TCHAR strNumberPlayers[32];
wsprintf( strNumberPlayers, TEXT("%d"), g_lNumberOfActivePlayers );
SetDlgItemText( hDlg, IDC_NUM_PLAYERS, strNumberPlayers );
break;
}
case WM_APP_CHAT:
{
HRESULT hr;
DPNID dpnidPlayer = (DPNID) wParam;
APP_PLAYER_INFO* pPlayerInfo = NULL;
PLAYER_LOCK(); // enter player context CS
// Get the player context accosicated with this DPNID
hr = g_pDP->GetPlayerContext( dpnidPlayer,
(LPVOID* const) &pPlayerInfo,
0);
PLAYER_ADDREF( pPlayerInfo ); // addref player, since we are using it now
PLAYER_UNLOCK(); // leave player context CS
APP_QUEUED_DATA* pQueuedData = (APP_QUEUED_DATA*) lParam;
if( FAILED(hr) || pPlayerInfo == NULL )
{
// The player who sent this may have gone away before this
// message was handled, so just ignore it
if( pQueuedData )
{
g_pDP->ReturnBuffer( pQueuedData->hBufferHandle,0 );
SAFE_DELETE( pQueuedData );
}
break;
}
// Add the message to the local listbox
HWND hWndChatBox = GetDlgItem( hDlg, IDC_CHAT_LISTBOX );
int nCount = (int)SendMessage( hWndChatBox, LB_GETCOUNT, 0, 0 );
if( nCount > MAX_CHAT_STRINGS )
SendMessage( hWndChatBox, LB_DELETESTRING, 0, 0 );
// Make the chat string from the player's name and the edit box string
TCHAR strChatBuffer[MAX_PLAYER_NAME + MAX_CHAT_STRING_LENGTH + 32];
wsprintf( strChatBuffer, TEXT("<%s> %s"), pPlayerInfo->strPlayerName, pQueuedData->pChatMsg->strChatString );
PLAYER_LOCK(); // enter player context CS
PLAYER_RELEASE( pPlayerInfo ); // Release player and cleanup if needed
PLAYER_UNLOCK(); // leave player context CS
// Add it, and make sure it is visible
int nIndex = (int)SendMessage( hWndChatBox, LB_ADDSTRING, 0, (LPARAM)strChatBuffer );
SendMessage( hWndChatBox, LB_SETTOPINDEX, nIndex, 0 );
// Done with the buffer, so return it DirectPlay,
// so that the memory can be reused
g_pDP->ReturnBuffer( pQueuedData->hBufferHandle,0 );
SAFE_DELETE( pQueuedData );
break;
}
case WM_COMMAND:
switch( LOWORD(wParam) )
{
case IDC_CHAT_EDIT:
if( HIWORD(wParam) == EN_UPDATE )
{
BOOL bEnableSend;
if( 0 == GetWindowTextLength( GetDlgItem( hDlg, IDC_CHAT_EDIT ) ) )
bEnableSend = FALSE;
else
bEnableSend = TRUE;
EnableWindow( GetDlgItem( hDlg, IDC_SEND ), bEnableSend );
}
break;
case IDC_SEND:
// The enter key was pressed, so send out the chat message
if( FAILED( g_hrDialog = SendChatMessage( hDlg ) ) )
{
DXTRACE_ERR( TEXT("SendChatMessage"), g_hrDialog );
EndDialog( hDlg, 0 );
}
break;
case IDCANCEL:
g_hrDialog = S_OK;
EndDialog( hDlg, 0 );
return TRUE;
}
break;
}
return FALSE; // Didn't handle message
}
//-----------------------------------------------------------------------------
// Name: OnInitDialog()
// Desc: Inits the dialog for the chat client.
//-----------------------------------------------------------------------------
HRESULT OnInitDialog( HWND hDlg )
{
// Load and set the icon
HICON hIcon = LoadIcon( g_hInst, MAKEINTRESOURCE( IDI_MAIN ) );
SendMessage( hDlg, WM_SETICON, ICON_BIG, (LPARAM) hIcon ); // Set big icon
SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon ); // Set small icon
// Display local player's name
SetDlgItemText( hDlg, IDC_PLAYER_NAME, g_strLocalPlayerName );
PostMessage( hDlg, WM_APP_UPDATE_STATS, 0, 0 );
SetFocus( GetDlgItem( hDlg, IDC_CHAT_EDIT ) );
SendMessage( GetDlgItem( hDlg, IDC_CHAT_EDIT ), EM_SETEVENTMASK, 0, ENM_UPDATE );
EnableWindow( GetDlgItem( hDlg, IDC_SEND ), FALSE );
if( g_pNetConnectWizard->IsHostPlayer() )
SetWindowText( hDlg, TEXT("ChatPeer (Host)") );
else
SetWindowText( hDlg, TEXT("ChatPeer") );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: DirectPlayMessageHandler
// Desc: Handler for DirectPlay messages. This function is called by
// the DirectPlay message handler pool of threads, so be care of thread
// synchronization problems with shared memory
//-----------------------------------------------------------------------------
HRESULT WINAPI DirectPlayMessageHandler( PVOID pvUserContext,
DWORD dwMessageId,
PVOID pMsgBuffer )
{
// Try not to stay in this message handler for too long, otherwise
// there will be a backlog of data. The best solution is to
// queue data as it comes in, and then handle it on other threads
// as this sample shows
// This function is called by the DirectPlay message handler pool of
// threads, so be care of thread synchronization problems with shared memory
HRESULT hReturn = S_OK;
switch( dwMessageId )
{
case DPN_MSGID_CREATE_PLAYER:
{
HRESULT hr;
PDPNMSG_CREATE_PLAYER pCreatePlayerMsg;
pCreatePlayerMsg = (PDPNMSG_CREATE_PLAYER)pMsgBuffer;
// Create a new and fill in a APP_PLAYER_INFO
APP_PLAYER_INFO* pPlayerInfo = new APP_PLAYER_INFO;
ZeroMemory( pPlayerInfo, sizeof(APP_PLAYER_INFO) );
pPlayerInfo->dpnidPlayer = pCreatePlayerMsg->dpnidPlayer;
pPlayerInfo->lRefCount = 1;
// Get the peer info and extract its name
DWORD dwSize = 0;
DPN_PLAYER_INFO* pdpPlayerInfo = NULL;
hr = DPNERR_CONNECTING;
// GetPeerInfo might return DPNERR_CONNECTING when connecting,
// so just keep calling it if it does
while( hr == DPNERR_CONNECTING )
hr = g_pDP->GetPeerInfo( pCreatePlayerMsg->dpnidPlayer, pdpPlayerInfo, &dwSize, 0 );
if( hr == DPNERR_BUFFERTOOSMALL )
{
pdpPlayerInfo = (DPN_PLAYER_INFO*) new BYTE[ dwSize ];
ZeroMemory( pdpPlayerInfo, dwSize );
pdpPlayerInfo->dwSize = sizeof(DPN_PLAYER_INFO);
hr = g_pDP->GetPeerInfo( pCreatePlayerMsg->dpnidPlayer, pdpPlayerInfo, &dwSize, 0 );
if( SUCCEEDED(hr) )
{
// This stores a extra TCHAR copy of the player name for
// easier access. This will be redundent copy since DPlay
// also keeps a copy of the player name in GetPeerInfo()
DXUtil_ConvertWideStringToGeneric( pPlayerInfo->strPlayerName,
pdpPlayerInfo->pwszName, MAX_PLAYER_NAME );
if( pdpPlayerInfo->dwPlayerFlags & DPNPLAYER_LOCAL )
g_dpnidLocalPlayer = pCreatePlayerMsg->dpnidPlayer;
}
SAFE_DELETE_ARRAY( pdpPlayerInfo );
}
// Tell DirectPlay to store this pPlayerInfo
// pointer in the pvPlayerContext.
pCreatePlayerMsg->pvPlayerContext = pPlayerInfo;
// Update the number of active players, and
// post a message to the dialog thread to update the
// UI. This keeps the DirectPlay message handler
// from blocking
InterlockedIncrement( &g_lNumberOfActivePlayers );
if( g_hDlg != NULL )
PostMessage( g_hDlg, WM_APP_UPDATE_STATS, 0, 0 );
break;
}
case DPN_MSGID_DESTROY_PLAYER:
{
PDPNMSG_DESTROY_PLAYER pDestroyPlayerMsg;
pDestroyPlayerMsg = (PDPNMSG_DESTROY_PLAYER)pMsgBuffer;
APP_PLAYER_INFO* pPlayerInfo = (APP_PLAYER_INFO*) pDestroyPlayerMsg->pvPlayerContext;
PLAYER_LOCK(); // enter player context CS
PLAYER_RELEASE( pPlayerInfo ); // Release player and cleanup if needed
PLAYER_UNLOCK(); // leave player context CS
// Update the number of active players, and
// post a message to the dialog thread to update the
// UI. This keeps the DirectPlay message handler
// from blocking
InterlockedDecrement( &g_lNumberOfActivePlayers );
if( g_hDlg != NULL )
PostMessage( g_hDlg, WM_APP_UPDATE_STATS, 0, 0 );
break;
}
case DPN_MSGID_HOST_MIGRATE:
{
PDPNMSG_HOST_MIGRATE pHostMigrateMsg;
pHostMigrateMsg = (PDPNMSG_HOST_MIGRATE)pMsgBuffer;
if( pHostMigrateMsg->dpnidNewHost == g_dpnidLocalPlayer )
SetWindowText( g_hDlg, TEXT("ChatPeer (Host)") );
break;
}
case DPN_MSGID_TERMINATE_SESSION:
{
PDPNMSG_TERMINATE_SESSION pTerminateSessionMsg;
pTerminateSessionMsg = (PDPNMSG_TERMINATE_SESSION)pMsgBuffer;
g_hrDialog = DPNERR_CONNECTIONLOST;
EndDialog( g_hDlg, 0 );
break;
}
case DPN_MSGID_RECEIVE:
{
PDPNMSG_RECEIVE pReceiveMsg;
pReceiveMsg = (PDPNMSG_RECEIVE)pMsgBuffer;
APP_PLAYER_INFO* pPlayerInfo = (APP_PLAYER_INFO*) pReceiveMsg->pvPlayerContext;
if( NULL == pPlayerInfo )
break;
GAMEMSG_GENERIC* pMsg = (GAMEMSG_GENERIC*) pReceiveMsg->pReceiveData;
if( pMsg->nType == GAME_MSGID_CHAT )
{
// This message is sent when a player has send a chat message to us, so
// post a message to the dialog thread to update the UI.
// This keeps the DirectPlay threads from blocking, and also
// serializes the recieves since DirectPlayMessageHandler can
// be called simultaneously from a pool of DirectPlay threads.
GAMEMSG_CHAT* pChatMessage = (GAMEMSG_CHAT*) pMsg;
// Record the buffer handle so the buffer can be returned later
APP_QUEUED_DATA* pQueuedData = new APP_QUEUED_DATA;
pQueuedData->hBufferHandle = pReceiveMsg->hBufferHandle;
pQueuedData->pChatMsg = pChatMessage;
// Pass the APP_QUEUED_DATA to the main dialog thread, so it can
// process it. It will also cleanup the struct
PostMessage( g_hDlg, WM_APP_CHAT,
pPlayerInfo->dpnidPlayer, (LPARAM) pQueuedData );
// Tell DirectPlay to assume that ownership of the buffer
// has been transferred to the application, and so it will
// neither free nor modify it until ownership is returned
// to DirectPlay through the ReturnBuffer() call.
hReturn = DPNSUCCESS_PENDING;
}
break;
}
}
// Make sure the DirectPlay MessageHandler calls the CNetConnectWizard handler,
// so it can be informed of messages such as DPN_MSGID_ENUM_HOSTS_RESPONSE.
if( hReturn != DPNSUCCESS_PENDING && SUCCEEDED(hReturn) && g_pNetConnectWizard )
hReturn = g_pNetConnectWizard->MessageHandler( pvUserContext, dwMessageId, pMsgBuffer );
return hReturn;
}
//-----------------------------------------------------------------------------
// Name: DirectPlayLobbyMessageHandler
// Desc: Handler for DirectPlay lobby messages. This function is called by
// the DirectPlay lobby message handler pool of threads, so be careful of
// thread synchronization problems with shared memory
//-----------------------------------------------------------------------------
HRESULT WINAPI DirectPlayLobbyMessageHandler( PVOID pvUserContext,
DWORD dwMessageId,
PVOID pMsgBuffer )
{
switch( dwMessageId )
{
case DPL_MSGID_CONNECT:
{
PDPL_MESSAGE_CONNECT pConnectMsg;
pConnectMsg = (PDPL_MESSAGE_CONNECT)pMsgBuffer;
// The CNetConnectWizard will handle this message for us,
// so there is nothing we need to do here for this simple
// sample.
break;
}
case DPL_MSGID_DISCONNECT:
{
PDPL_MESSAGE_DISCONNECT pDisconnectMsg;
pDisconnectMsg = (PDPL_MESSAGE_DISCONNECT)pMsgBuffer;
// We should free any data associated with the lobby
// client here, but there is none.
break;
}
case DPL_MSGID_RECEIVE:
{
PDPL_MESSAGE_RECEIVE pReceiveMsg;
pReceiveMsg = (PDPL_MESSAGE_RECEIVE)pMsgBuffer;
// The lobby client sent us data. This sample doesn't
// expected data from the client, but it is useful
// for more complex apps.
break;
}
case DPL_MSGID_CONNECTION_SETTINGS:
{
PDPL_MESSAGE_CONNECTION_SETTINGS pConnectionStatusMsg;
pConnectionStatusMsg = (PDPL_MESSAGE_CONNECTION_SETTINGS)pMsgBuffer;
// The lobby client has changed the connection settings.
// This simple sample doesn't handle this, but more complex apps may
// want to.
break;
}
}
// Make sure the DirectPlay MessageHandler calls the CNetConnectWizard handler,
// so the wizard can be informed of lobby messages such as DPL_MSGID_CONNECT
if( g_pNetConnectWizard )
return g_pNetConnectWizard->LobbyMessageHandler( pvUserContext, dwMessageId,
pMsgBuffer );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: SendChatMessage()
// Desc: Create chat string based on the editbox and send it to everyone
//-----------------------------------------------------------------------------
HRESULT SendChatMessage( HWND hDlg )
{
// Get length of item text
DWORD dwEditboxBufferSize = (DWORD)SendDlgItemMessage( hDlg, IDC_CHAT_EDIT,
WM_GETTEXTLENGTH, 0, 0 );
if( dwEditboxBufferSize == 0 )
return S_OK; // Don't do anything for blank messages
GAMEMSG_CHAT msgChat;
msgChat.nType = GAME_MSGID_CHAT;
GetDlgItemText( hDlg, IDC_CHAT_EDIT, msgChat.strChatString, MAX_CHAT_STRING_LENGTH );
// Set the dwBufferSize to only send the string that has valid text in it.
// Otherwise bandwidth is wasted.
DPN_BUFFER_DESC bufferDesc;
bufferDesc.dwBufferSize = sizeof(msgChat.nType) +
(_tcslen(msgChat.strChatString)+1)*sizeof(TCHAR);
bufferDesc.pBufferData = (BYTE*) &msgChat;
// Send it to all of the players include the local client
// DirectPlay will tell via the message handler
// if there are any severe errors, so ignore any errors
DPNHANDLE hAsync;
g_pDP->SendTo( DPNID_ALL_PLAYERS_GROUP, &bufferDesc, 1,
0, NULL, &hAsync, DPNSEND_GUARANTEED );
// Blank out edit box
SetDlgItemText( hDlg, IDC_CHAT_EDIT, TEXT("") );
return S_OK;
}

View File

@@ -0,0 +1,204 @@
# Microsoft Developer Studio Project File - Name="ChatPeer" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Application" 0x0101
CFG=ChatPeer - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "ChatPeer.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "ChatPeer.mak" CFG="ChatPeer - Win32 Debug Unicode"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "ChatPeer - Win32 Debug Unicode" (based on "Win32 (x86) Application")
!MESSAGE "ChatPeer - Win32 Release Unicode" (based on "Win32 (x86) Application")
!MESSAGE "ChatPeer - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "ChatPeer - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "ChatPeer - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I "..\..\common\include" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /D "_WIN32_DCOM" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 dplay.lib dxguid.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib odbc32.lib odbccp32.lib dxerr8.lib winmm.lib kernel32.lib user32.lib ole32.lib uuid.lib /nologo /subsystem:windows /machine:I386 /stack:0x10000,0x10000
!ELSEIF "$(CFG)" == "ChatPeer - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\common\include" /D "_WINDOWS" /D "_DEBUG" /D "WIN32" /D "_WIN32_DCOM" /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
# ADD LINK32 dplay.lib dxguid.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib odbc32.lib odbccp32.lib dxerr8.lib winmm.lib kernel32.lib user32.lib ole32.lib uuid.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"LIBC" /pdbtype:sept /stack:0x10000,0x10000
# SUBTRACT LINK32 /incremental:no /nodefaultlib
!ELSEIF "$(CFG)" == "ChatPeer - Win32 Debug Unicode"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Win32_Debug_Unicode"
# PROP BASE Intermediate_Dir "Win32_Debug_Unicode"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Win32_Debug_Unicode"
# PROP Intermediate_Dir "Win32_Debug_Unicode"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\common\include" /D "_WINDOWS" /D "_DEBUG" /D "WIN32" /D "_WIN32_DCOM" /YX /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /I "..\..\common\include" /D "_DEBUG" /D "_WINDOWS" /D "WIN32" /D "_WIN32_DCOM" /D "UNICODE" /D "_UNICODE" /YX /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 dplay.lib dxguid.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib odbc32.lib odbccp32.lib dxerr8.lib winmm.lib kernel32.lib user32.lib ole32.lib uuid.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"LIBC" /pdbtype:sept
# SUBTRACT BASE LINK32 /incremental:no /nodefaultlib
# ADD LINK32 dplay.lib dxguid.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib odbc32.lib odbccp32.lib dxerr8.lib winmm.lib kernel32.lib user32.lib ole32.lib uuid.lib /nologo /subsystem:windows /debug /machine:I386 /nodefaultlib:"LIBC" /pdbtype:sept /stack:0x10000,0x10000
# SUBTRACT LINK32 /incremental:no /nodefaultlib
!ELSEIF "$(CFG)" == "ChatPeer - Win32 Release Unicode"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Win32_Release_Unicode"
# PROP BASE Intermediate_Dir "Win32_Release_Unicode"
# PROP BASE Ignore_Export_Lib 0
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Win32_Release_Unicode"
# PROP Intermediate_Dir "Win32_Release_Unicode"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "." /I "..\..\common\include" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "WIN32" /D "_WIN32_DCOM" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "." /I "..\..\common\include" /D "NDEBUG" /D "_MBCS" /D "_WINDOWS" /D "WIN32" /D "_WIN32_DCOM" /D "UNICODE" /D "_UNICODE" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 dplay.lib dxguid.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib odbc32.lib odbccp32.lib dxerr8.lib winmm.lib kernel32.lib user32.lib ole32.lib uuid.lib /nologo /subsystem:windows /machine:I386
# ADD LINK32 dplay.lib dxguid.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib oleaut32.lib odbc32.lib odbccp32.lib dxerr8.lib winmm.lib kernel32.lib user32.lib ole32.lib uuid.lib /nologo /subsystem:windows /machine:I386 /stack:0x10000,0x10000
!ENDIF
# Begin Target
# Name "ChatPeer - Win32 Release"
# Name "ChatPeer - Win32 Debug"
# Name "ChatPeer - Win32 Debug Unicode"
# Name "ChatPeer - Win32 Release Unicode"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\ChatPeer.cpp
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# Begin Source File
SOURCE=.\ChatPeer.rc
# End Source File
# Begin Source File
SOURCE=.\directx.ico
# End Source File
# Begin Source File
SOURCE=.\resource.h
# End Source File
# End Group
# Begin Group "Common"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\common\src\dxutil.cpp
# End Source File
# Begin Source File
SOURCE=..\..\common\include\dxutil.h
# End Source File
# Begin Source File
SOURCE=..\..\common\src\NetConnect.cpp
# End Source File
# Begin Source File
SOURCE=..\..\common\include\NetConnect.h
# End Source File
# Begin Source File
SOURCE=..\..\common\include\netconnectres.h
# End Source File
# End Group
# Begin Source File
SOURCE=.\readme.txt
# End Source File
# End Target
# End Project

View File

@@ -0,0 +1,199 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_MULTIPLAYER_CONNECT DIALOG DISCARDABLE 0, 0, 282, 151
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Multiplayer Connect"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Player Name:",IDC_STATIC,7,10,43,8
EDITTEXT IDC_PLAYER_NAME_EDIT,7,22,268,14,ES_AUTOHSCROLL
LTEXT "Connection Type:",IDC_STATIC,7,41,57,8
LISTBOX IDC_CONNECTION_LIST,7,53,268,72,LBS_SORT |
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
DEFPUSHBUTTON "OK",IDOK,171,130,50,14
PUSHBUTTON "Cancel",IDCANCEL,225,130,50,14
END
IDD_MULTIPLAYER_GAMES DIALOG DISCARDABLE 0, 0, 282, 140
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Multiplayer Games"
FONT 8, "MS Shell Dlg"
BEGIN
LTEXT "Select Game To Join:",-1,7,15,69,8
CONTROL "Start Search",IDC_SEARCH_CHECK,"Button",BS_AUTOCHECKBOX |
BS_PUSHLIKE | WS_TABSTOP,220,7,55,14
LISTBOX IDC_GAMES_LIST,7,24,268,91,LBS_SORT |
LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Join",IDC_JOIN,7,119,50,14
PUSHBUTTON "Create",IDC_CREATE,61,119,50,14
PUSHBUTTON "Cancel",IDC_BACK,225,119,50,14
END
IDD_LOBBY_WAIT_STATUS DIALOG DISCARDABLE 120, 110, 162, 52
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION
CAPTION "Lobby Connection Status"
FONT 8, "MS Shell Dlg"
BEGIN
DEFPUSHBUTTON "&Cancel",IDCANCEL,55,31,51,14
CTEXT "Finding Game...",IDC_WAIT_TEXT,7,14,141,8
END
IDD_MULTIPLAYER_CREATE DIALOG DISCARDABLE 0, 0, 186, 77
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Create Game"
FONT 8, "MS Shell Dlg"
BEGIN
EDITTEXT IDC_EDIT_SESSION_NAME,7,19,172,14,ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,7,56,50,14
PUSHBUTTON "Cancel",IDCANCEL,129,56,50,14
LTEXT "Game Name:",IDC_STATIC,7,7,42,8
CONTROL "Migrate Host",IDC_MIGRATE_HOST,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,66,40,56,10
END
IDD_MAIN_GAME DIALOG DISCARDABLE 0, 0, 262, 156
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_VISIBLE | WS_CAPTION |
WS_SYSMENU
CAPTION "DirectPlay Chat Sample"
FONT 8, "MS Shell Dlg"
BEGIN
PUSHBUTTON "Exit",IDCANCEL,199,16,50,14
EDITTEXT IDC_CHAT_EDIT,14,130,184,14,ES_WANTRETURN
LISTBOX IDC_CHAT_LISTBOX,14,34,235,95,WS_VSCROLL | WS_TABSTOP
LTEXT "Number of people in conversation:",IDC_STATIC,14,19,109,
8
LTEXT "0",IDC_NUM_PLAYERS,127,19,54,8
DEFPUSHBUTTON "Send",IDC_SEND,199,130,50,14
GROUPBOX "",IDC_STATIC,7,7,248,142
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO DISCARDABLE
BEGIN
IDD_MULTIPLAYER_CONNECT, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 275
TOPMARGIN, 7
BOTTOMMARGIN, 144
END
IDD_MULTIPLAYER_GAMES, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 275
VERTGUIDE, 141
TOPMARGIN, 7
BOTTOMMARGIN, 133
END
IDD_LOBBY_WAIT_STATUS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 148
TOPMARGIN, 7
BOTTOMMARGIN, 45
END
IDD_MULTIPLAYER_CREATE, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 179
VERTGUIDE, 94
TOPMARGIN, 7
BOTTOMMARGIN, 70
END
IDD_MAIN_GAME, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 255
TOPMARGIN, 7
BOTTOMMARGIN, 149
END
END
#endif // APSTUDIO_INVOKED
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_MAIN ICON DISCARDABLE "directx.ico"
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,96 @@
//-----------------------------------------------------------------------------
//
// Sample Name: ChatPeer Sample
//
// Copyright (c) 1999-2001 Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
Description
===========
ChatPeer is similar in form to SimplePeer. Once a player hosts or connects
to a session, the players can chat with either other by passing text
strings.
Path
====
Source: DXSDK\Samples\Multimedia\DirectPlay\ChatPeer
Executable: DXSDK\Samples\Multimedia\DirectPlay\Bin
User's Guide
============
Refer to User's Guide section of the SimplePeer sample.
Programming Notes
=================
The ChatPeer sample is very similar in form to the SimplePeer sample. For
detailed programming notes on the basics this sample, refer to Programming
Notes section of the SimplePeer sample.
The ChatPeer differs by letting clients send text strings to all players
connected to the session.
* The "Send" button is pressed. See SendChatMessage().
1. Retrieves the text string from the dialog.
2. Fills a app defined struct, GAMEMSG_CHAT. This struct has
a message type ID as the first BYTE. This lets our app
figure out what type of app message they received, however
ChatPeer only uses one app defined message. See StagedPeer
for a more complex example of this process.
3. Fills out a DPN_BUFFER_DESC struct using the GAMEMSG_CHAT buffer.
4. Calls IDirectPlay8Peer::SendTo() with the DPN_BUFFER_DESC. It passes
DPNID_ALL_PLAYERS_GROUP so this message goes to everyone.
* Handle DirectPlay system messages. See DirectPlayMessageHandler()
The ChatPeer handles the typical messages as described in the
SimplePeer programming notes, and in addition:
- Upon DPN_MSGID_RECEIVE message:
1. It casts pReceiveMsg->pReceiveData into a generic app defined
structure, GAMEMSG_GENERIC. This helps to figure out what structure
is really contained in pReceiveMsg->pReceiveData. For this simple
example, if the ID is GAME_MSGID_CHAT it casts the buffer to a
GAMEMSG_CHAT*.
2. It then creates a new APP_QUEUED_DATA struct which contains a pointer
to the GAMEMSG_CHAT buffer, and the a DirectPlay handle linked to the
GAMEMSG_CHAT buffer.
3. We then post a user defined message, WM_APP_CHAT, to the dialog thread
with the lParam equal to a pointer to the APP_QUEUED_DATA struct and
the wParam equal to the DPNID of the player who sent us the buffer.
We post a message since this lets us return from the DirectPlay message
handler quickly. In a complex game if the handler threads take too
long its possible that a backlog of network data may arise.
4. We return from DirectPlayMessageHandler() with the result code
of DPNSUCCESS_PENDING. This error code tells DirectPlay that the buffer
we got in the DPN_MSGID_RECEIVE message is still in use by our app.
This allows us to not to have to copy the buffer, but instead pass a
pointer of it off to a worker thread. This simple sample just uses
the main dialog thread to process queued data. For a more complex
example of this process see the DataRelay sample.
* Upon receiving WM_APP_CHAT in the message loop
This is posted to the message loop by one DirectPlay message handler threads
whenever we receive a chat message. See above for more detail. Here's what
happens:
1. Cast the wParam to a DPNID. This is the player that sent the message.
2. Calls IDirectPlay8Peer::GetPlayerContext(). This retrieves a user
specified pointer (which we cast to a APP_PLAYER_INFO*) associated with
this player. See the SimplePeer programming notes for more info on how
this is setup. Also, note that since player can be deleted at any time,
we need to use ref counting to make sure this player context struct isn't
deleted while we are still using it.
3. Cast the lParam into a APP_QUEUED_DATA*. This tells us the buffer, and the DirectPlay
handle associated with that buffer.
4. Process the buffer by adding it's text string to the dialog.
5. Release the APP_PLAYER_INFO* since we are done using it.
6. Now DirectPlay can free the receive buffer since we are done with it.
So return the buffer to DirectPlay by calling IDirectPlay8Peer::ReturnBuffer,
passing in the DirectPlay buffer handle.
7. Deletes the APP_QUEUED_DATA from the heap

View File

@@ -0,0 +1,39 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by ChatPeer.rc
//
#define IDD_MAIN_GAME 101
#define IDC_WAVE 1001
#define IDC_NUM_PLAYERS 1002
#define IDC_PLAYER_NAME 1003
#define IDC_CHAT_EDIT 1010
#define IDC_CHAT_LISTBOX 1012
#define IDC_SEND 1034
#define IDD_MULTIPLAYER_CONNECT 10001
#define IDD_MULTIPLAYER_GAMES 10002
#define IDD_MULTIPLAYER_CREATE 10003
#define IDD_LOBBY_WAIT_STATUS 10004
#define IDC_RETURN 11001
#define IDC_PLAYER_NAME_EDIT 11002
#define IDC_GAMES_LIST 11003
#define IDC_JOIN 11004
#define IDC_CREATE 11005
#define IDC_CONNECTION_LIST 11006
#define IDC_BACK 11007
#define IDC_CHECK_DPLAY_PROTOCOL 11008
#define IDC_EDIT_SESSION_NAME 11009
#define IDC_SEARCH_CHECK 11010
#define IDC_WAIT_TEXT 11012
#define IDC_MIGRATE_HOST 11013
#define IDI_MAIN 11014
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 105
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1004
#define _APS_NEXT_SYMED_VALUE 103
#endif
#endif