m.shuhrat

   Good evening all,

I just cannot seem to get a list of Lobby aware applications registered on my system. I know there are two games that are listed on dxdiag's Network tab, and shown as Lobbyable applications. But when I execute:

Microsoft.DirectX.DirectPlay.Lobby.Client.GetLocalPrograms() and try to attach to a listbox, nothing happens. The array is empty. Any idea why

I have DX9 installed. Is it backward compatibily issue or something I'm missing

Regards,

Shuhrat



Re: Game Technologies: General Cannot get a list of Lobby aware applications (C#)

m.shuhrat

Basically what I'm trying to achive is to get following piece of code working:

connection = new Microsoft.DirectX.DirectPlay.Lobby.Client();

ConnectInformation sets = new ConnectInformation();

sets.GuidApplication = new Guid("{5DE93F3F-FC90-4ee1-AE5A-63DAFA055950}");

sets.Flags = Microsoft.DirectX.DirectPlay.Lobby.ConnectFlags.LaunchNotFound;

sets.UseConnectionSettings = true;

Address address = new Address();

Guid tes = new Guid("{4CE725F6-D3C0-4796-BA6F-11F965BC4299}");

address.Device = tes;

address.ServiceProvider = Address.ServiceProviderTcpIp;

address.AddComponent(Address.KeyHostname, "localhost");

address.AddComponent(Address.KeyPort, 47694);

sets.ConnectionSettings.HostAddress = address;

sets.ConnectionSettings.PlayerName = "Amaki";

connection.ConnectApplication(sets, System.Threading.Timeout.Infinite, null);

After following line

Address address = new Address();

when I debug I can see that Device property of object is throwing exception:

Device 'address.Device' threw an exception of type 'Microsoft.DirectX.DirectPlay.DoesNotExistException' System.Guid {Microsoft.DirectX.DirectPlay.DoesNotExistException}

after which I tried to set my NIC GUID manually. but still I get this exception after the last line.

Microsoft.DirectX.DirectPlay.InvalidDeviceAddressException was caught
Message="Error in the application."
Source="Microsoft.DirectX.DirectPlay"
ErrorCode=-2146073824
ErrorString="DPNERR_INVALIDDEVICEADDRESS"
StackTrace:
at Microsoft.DirectX.DirectPlay.Lobby.Client.ConnectApplication(ConnectInformation connectInformation, Int32 timeOut, Object applicationContext)
at LobbyTest.Form1.button1_Click(Object sender, EventArgs e) in D:\Documents\Shukhrat\Visual Studio Projects\LobbyTest\LobbyTest\Form1.cs:line 37



any ideas/tips/help appreciated






Re: Game Technologies: General Cannot get a list of Lobby aware applications (C#)

The ZMan

There are few DirectPlay experts life out there so you might not get much help. Plus DirectPlay is no longer supported so you can't even get official support.

One thing you could try is to get an old SDK that had some DirectPlay samples included (sorry I can't guess how far back you might have to go but try starting with summer 04 which was a solid MDX refresh).

The other thing you can try is to turn on full debugging on the directx control panel for DirectInput and then change your porject settings to 'allow unmanaged debugging'. You may see something in the debug output that will help you.






Re: Game Technologies: General Cannot get a list of Lobby aware applications (C#)

DejanP

That's look you trying to start AOC :)

I am using pointer to structure, so, those interfaces aren't familiar to me but I notice that you totally missing session info. Search for :

DPLCONNECTION_CREATESESSION
DPLCONNECTION_JOINSESSION

and you ashall find answer.

btw. When you are host not needed to put anything in host & port, Direct Play will assign first unused port between 2300 and 2400, you only need to provide IP when client need to join session.

how this working really look in my lobby http://www.ztbclan.com/zone/




Re: Game Technologies: General Cannot get a list of Lobby aware applications (C#)

m.shuhrat

hey fellow man:))

yes I want to do exactly what u did. but I'm a C# programmer, but in C# I cannot specify which interface of DX to use. it uses Direcplay8 interface where as AOC was written in previous interfaces. May be there is a way of specifying interface but I could not find yet. Did u program in C++

Regards

Shuhrat





Re: Game Technologies: General Cannot get a list of Lobby aware applications (C#)

DejanP

There is no point which DX to use, I said that you need to fill session info data and to assign that somewhere, your classes shall handle this interface. Maybe you shall look in MSDN October 2000 (or before) for some more data.

I did that in delphi, in C++ this shall take eternity for me to finish that :)

btw. Where you planing to put that, which one site I am about to finish new version (existing one is made 6 months ago and didn't had time to work on that till now) and after that need to do game reverse engenering in order to made ratings, Microsoft don't want to publish game starting protocol, need to do it dirty :(

If you didn't made to much maybe you shall think about some other programming language Many people still don't have .net installed, you don't need .net for that. Also, working with pointer shall be faster then all of that on server side, I didn't had enought users for a moment but calculating that my actual server can handle > 10.000 players in time with no lag, don't think you can do it with .net.





Re: Game Technologies: General Cannot get a list of Lobby aware applications (C#)

m.shuhrat

as I understant u didnt use managed DX Can I email you or ICQ you



Re: Game Technologies: General Cannot get a list of Lobby aware applications (C#)

m.shuhrat

Here is main part of launching a game, but when it launches it does not create a host session, all I can see is "Unable to join game" message. What am I doing wrong I dont know what site I'm going to set it up. My clan is www.pycclan.ru, but it is in PHP, so dont know yet. Please I know it is nearly working, but cannot see how to finish it.

BOOL FAR PASCAL EnumAddressTypes( REFGUID guidAddressType, VOID* pContext,

DWORD dwFlags )

{

ADDRESSTYPELIST* pAddressTypes = (ADDRESSTYPELIST*)pContext;

if( pAddressTypes->dwCount < 10 )

{

// Save the address type guid in the list

pAddressTypes->guidAddressTypes[pAddressTypes->dwCount] = guidAddressType;

pAddressTypes->dwCount++;

}

return TRUE;

}

HRESULT CreateAddress( HWND hWnd, GUID* pServiceProviderGUID, VOID** ppAddress,

DWORD* pdwAddressSize )

{

ADDRESSTYPELIST addressTypeList;

DPCOMPOUNDADDRESSELEMENT addressElements[11];

GUID guidAddressType;

VOID* pAddress = NULL;

DWORD dwAddressSize = 0;

DWORD i;

DWORD dwElementCount;

HRESULT hr;

char *ipAddress="192.168.1.2";

// Get the list of address types for this service provider

ZeroMemory( &addressTypeList, sizeof(ADDRESSTYPELIST) );

hr = pDPLClient->EnumAddressTypes( EnumAddressTypes, *pServiceProviderGUID,

&addressTypeList, 0L );

if( FAILED(hr) )

return hr;

dwElementCount = 0;

// All DPADDRESS's must have a service provider chunk

addressElements[dwElementCount].guidDataType = DPAID_ServiceProvider;

addressElements[dwElementCount].dwDataSize = sizeof(GUID);

addressElements[dwElementCount].lpData = pServiceProviderGUID;

dwElementCount++;

_stprintf(str, _T("dwCount 2 is %d"), addressTypeList.dwCount);

MessageBox(0, str, 0, MB_OK);

// Loop over the address types

for( i = 0; i < addressTypeList.dwCount; i++ )

{

guidAddressType = addressTypeList.guidAddressTypesIdea;

if( IsEqualGUID( guidAddressType, DPAID_INet ) )

{

// Add an IP address chunk

addressElements[dwElementCount].guidDataType = DPAID_INet;

addressElements[dwElementCount].dwDataSize = lstrlen(ipAddress) + 1;

addressElements[dwElementCount].lpData = ipAddress;

dwElementCount++;

}

}

// Bail if no address data is available

if( dwElementCount == 1 )

return DPERR_GENERIC;

// See how much room is needed to store this address

hr = pDPLClient->CreateCompoundAddress( addressElements, dwElementCount,

NULL, &dwAddressSize );

if( hr != DPERR_BUFFERTOOSMALL )

return hr;

// Allocate space

pAddress = GlobalAllocPtr( GHND, dwAddressSize );

if( pAddress == NULL )

return DPERR_NOMEMORY;

// Create the address

hr = pDPLClient->CreateCompoundAddress( addressElements, dwElementCount,

pAddress, &dwAddressSize );

if( FAILED(hr) )

{

GlobalFreePtr( pAddress );

return hr;

}

// Return the address info

*ppAddress = pAddress;

*pdwAddressSize = dwAddressSize;

return DP_OK;

}

BOOL FAR PASCAL ConnectionEnumFunction(const GUID* pSPGUID, void *lpConnection, DWORD dwConnectionSize, const DPNAME* lpName, DWORD dwFlags, VOID *lpContext){

MessageBox(NULL, lpName->lpszShortNameA, "", MB_OK);

pAddress=lpConnection;

guidSP=(LPGUID)pSPGUID;

return TRUE;

}

HRESULT RunProgram(){

HRESULT hr;

TCHAR str[255];

CoCreateInstance(CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay4A, (VOID**)&pDPLobby);

CoCreateInstance(CLSID_DirectPlayLobby, NULL,CLSCTX_INPROC_SERVER, IID_IDirectPlayLobby3A, (VOID**)&pDPLClient);

pDPLClient->EnumLocalApplications(ApplicationEnumerationCallBack, NULL, 0);

//this is how I tried to create address. didnt work.

pDPLobby->EnumConnections(&gameGUID, ConnectionEnumFunction, &str, 0L);

//This is one way of creating address object

/*GUID inet=DPSPGUID_TCPIP;

CreateAddress( NULL, &inet,&pAddress,&addressSize );*/

//This is other way of creating address object

/*DPCOMPOUNDADDRESSELEMENT addEls[2];

char *ipAddress="192.168.1.2";

addEls[0].guidDataType=DPAID_ServiceProvider;

addEls[0].dwDataSize=sizeof(GUID);

addEls[0].lpData=(LPVOID)&DPSPGUID_TCPIP;

addEls[1].guidDataType=DPAID_INet;

addEls[1].dwDataSize=strlen(ipAddress)+1;

addEls[1].lpData=ipAddress;

pDPLClient->CreateCompoundAddress(addEls, 2, NULL, &addressSize);

pDPLClient->CreateCompoundAddress(addEls, 2, &pAddress, &addressSize);*/

DWORD appID;

DPLCONNECTION cInfo;

DPSESSIONDESC2 sessionInfo;

DPNAME playerName;

// Fill out session description

ZeroMemory( &sessionInfo, sizeof(DPSESSIONDESC2) );

sessionInfo.dwSize = sizeof(DPSESSIONDESC2);

sessionInfo.dwFlags = 0; // DPSESSION_xxx flags

sessionInfo.guidApplication = gameGUID; // GUID of the DirectPlay application.

sessionInfo.dwMaxPlayers = 0; // Maximum # players allowed in session

sessionInfo.dwCurrentPlayers = 0; // Current # players in session (read only)

sessionInfo.lpszSessionNameA = "Sameple"; // ANSI name of the session

sessionInfo.lpszPasswordA = NULL; // ANSI password of the session (optional)

sessionInfo.dwReserved1 = 0; // Reserved for future MS use.

sessionInfo.dwReserved2 = 0;

sessionInfo.dwUser1 = 0; // For use by the application

sessionInfo.dwUser2 = 0;

sessionInfo.dwUser3 = 0;

sessionInfo.dwUser4 = 0;

// Fill out player name

ZeroMemory( &playerName, sizeof(DPNAME) );

playerName.dwSize = sizeof(DPNAME);

playerName.dwFlags = 0; // Not used. Must be zero.

playerName.lpszShortNameA = "Test"; // ANSI short or friendly name

playerName.lpszLongNameA = "Test"; // ANSI long or formal name

// Fill out connection description

ZeroMemory( &cInfo, sizeof(DPLCONNECTION) );

cInfo.dwSize = sizeof(DPLCONNECTION);

cInfo.lpSessionDesc = &sessionInfo; // Pointer to session desc to use on connect

cInfo.lpPlayerName = &playerName; // Pointer to Player name structure

cInfo.guidSP = *guidSP; // GUID of the DPlay SP to use

cInfo.lpAddress = pAddress; // Address for service provider

cInfo.dwAddressSize = addressSize; // Size of address data

cInfo.dwFlags = DPLCONNECTION_CREATESESSION;

hr=pDPLClient->RunApplication( 0, &appID, &cInfo, NULL );

if(hr==DPERR_CANTCREATEPROCESS )

MessageBoxA(NULL, "Game is not installed", "", MB_OK);

else if(hr==DPERR_GENERIC )

MessageBoxA(NULL, "Game is not installed", "", MB_OK);

else if(hr==DPERR_INVALIDINTERFACE )

MessageBoxA(NULL, "DPERR_INVALIDINTERFACE ", "", MB_OK);

else if(hr==DPERR_INVALIDOBJECT )

MessageBoxA(NULL, "DPERR_INVALIDOBJECT ", "", MB_OK);

else if(hr==DPERR_INVALIDPARAMS )

MessageBoxA(NULL, "DPERR_INVALIDPARAMS ", "", MB_OK);

else if(hr==DPERR_OUTOFMEMORY )

MessageBoxA(NULL, "DPERR_OUTOFMEMORY ", "", MB_OK);

else if(hr==DPERR_UNKNOWNAPPLICATION )

MessageBoxA(NULL, "DPERR_UNKNOWNAPPLICATION ", "", MB_OK);

if(pDPLobby)

SAFE_RELEASE(pDPLobby);

if(pDPLClient)

SAFE_RELEASE(pDPLClient);

return DP_OK;

}





Re: Game Technologies: General Cannot get a list of Lobby aware applications (C#)

DejanP

where you allocating memory for sessionInfo and connectionInfo I am not familiar with this code, here is how I creating address (for IP only, who care about IPX, Modem, Serial ...)

procedure TfrmStarting.CreateAddress(host: string; Port: Word; server: boolean; var lpAddress: pointer; var dwAddressSize: Cardinal);
var
addressElements: array[0..2] of TDPCompoundAddressElement;
dwElementCount: Integer;
Lobby1: IDirectPlayLobbyA;
Lobby: IDirectPlayLobby2A;
begin
if DXDirectPlayLobbyCreateA(PGUID(nil)^, Lobby1, nil, nil, 0) <> 0 then raise EDDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]);
Lobby := Lobby1 as IDirectPlayLobby2A;

FillChar(addressElements, SizeOf(addressElements), 0);
dwElementCount := 0;

//TCP/IP
addressElements[dwElementCount].guidDataType := DPAID_ServiceProvider;
addressElements[dwElementCount].dwDataSize := SizeOf(TGUID);
addressElements[dwElementCount].lpData := @DPSPGUID_TCPIP;
Inc(dwElementCount);

if not server then
begin
addressElements[dwElementCount].guidDataType := DPAID_INet;
addressElements[dwElementCount].dwDataSize := Length(host);
addressElements[dwElementCount].lpData := PChar(host);
Inc(dwElementCount);
end;

if port <> 0 then
begin
addressElements[dwElementCount].guidDataType := DPAID_INetPort;
addressElements[dwElementCount].dwDataSize := SizeOf(port);
addressElements[dwElementCount].lpData := @port;
Inc(dwElementCount);
end;

if Lobby.CreateCompoundAddress(addressElements[0], dwElementCount, nil, dwAddressSize) <> DPERR_BUFFERTOOSMALL then
raise EDDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]);

GetMem(lpAddress, dwAddressSize);
try
FillChar(lpAddress^, dwAddressSize, 0);

if Lobby.CreateCompoundAddress(addressElements[0], dwElementCount, lpAddress, wAddressSize) <> 0 then
raise EDDXPlayError.CreateFmt(SCannotInitialized, [SDirectPlay]);

finally
// FreeMem(lpAddress);
end;
end;

so, addresselements array is enought to be length 3, you need to say that this is :
- TCP
- IP address
- port (optional, not needed really except if you don't want to force some port)

you code look ok, I just don't understeand all of that and ... pay atention, I had this problem when I was developing game starting :
lpAddress must be private or global variable, can't be local, must be visible when you starting game.

Anyway, "unable to join" mean that you trying to JOIN game, not to CREATE and as I see in your code you have set ok DPLCONNECTION_CREATESESSION which confuzing me :)

only one part where I making diference between create and join is :
if bHost then
connectInfo.dwFlags := DPLCONNECTION_CREATESESSION
else
connectInfo.dwFlags := DPLCONNECTION_JOINSESSION;

Also, pay atention that IP address is not needed in addressElements if you are the host, you need to set IP address only when you want to join created game. this is in code :
...
if not server then
begin
...

Sorry because didn't have right now better piece of code but I tottaly mess this source, in this moment trying to found how to send aditional settings to game and my source code is chaostic :)


good luck




Re: Game Technologies: General Cannot get a list of Lobby aware applications (C#)

m.shuhrat

DejanP,

Thank you for your input. I will try that and will let you know about outcome.

Shuhrat