| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- /*
- Note - does not appear to like DPSESSION_MULTICASTSERVER very much!
- */
- #include "std.h"
- #include "multiplay.h"
- #include "multiplay_setup.h"
- struct Player;
- static bool host;
- static map<DPID,Player*> player_map;
- static list<Player*> players,new_players;
- static int msg_type;
- static string msg_data;
- static DPID msg_from,msg_to;
- static char *recv_buff;
- static int recv_buff_sz;
- static char *send_buff;
- static int send_buff_sz;
- #pragma pack( push,1 )
- struct bbMsg{
- DPID from,to;
- char type;
- };
- #pragma pack( pop )
- struct Player{
- DPID id;
- string name;
- bool remote;
- Player( DPID i,const string &n,bool r ):id(i),name(n),remote(r){
- players.push_back( this );
- if( remote ) new_players.push_back( this );
- player_map.clear();
- }
- Player::~Player(){
- new_players.remove( this );
- players.remove( this );
- player_map.clear();
- }
- };
- static void chk(){
- if( !dirPlay ){
- RTEX( "Multiplayer game not started" );
- }
- }
- static void clearPlayers(){
- while( players.size() ) delete players.back();
- new_players.clear();
- player_map.clear();
- }
- static Player *findPlayer( DPID id ){
- if( !player_map.size() ){
- list<Player*>::iterator it;
- for( it=players.begin();it!=players.end();++it ){
- player_map.insert( pair<DPID,Player*>( (*it)->id,(*it) ) );
- }
- }
- map<DPID,Player*>::iterator it=player_map.find( id );
- return it==player_map.end() ? 0 : it->second;
- }
- static BOOL FAR PASCAL enumPlayer( DPID id,DWORD type,LPCDPNAME name,DWORD flags,LPVOID context ){
- Player *p=findPlayer( id );if( p ) return TRUE;
- p=d_new Player( id,string( name->lpszShortNameA ),true );
- return TRUE;
- }
- void multiplay_link( void(*rtSym)(const char*,void*) ){
- rtSym( "%StartNetGame",bbStartNetGame );
- rtSym( "%HostNetGame$game_name",bbHostNetGame );
- rtSym( "%JoinNetGame$game_name$ip_address",bbJoinNetGame );
- rtSym( "StopNetGame",bbStopNetGame );
- rtSym( "%CreateNetPlayer$name",bbCreateNetPlayer );
- rtSym( "DeleteNetPlayer%player",bbDeleteNetPlayer );
- rtSym( "$NetPlayerName%player",bbNetPlayerName );
- rtSym( "%NetPlayerLocal%player",bbNetPlayerLocal );
- rtSym( "%SendNetMsg%type$msg%from_player%to_player=0%reliable=1",bbSendNetMsg );
- rtSym( "%RecvNetMsg",bbRecvNetMsg );
- rtSym( "%NetMsgType",bbNetMsgType );
- rtSym( "%NetMsgFrom",bbNetMsgFrom );
- rtSym( "%NetMsgTo",bbNetMsgTo );
- rtSym( "$NetMsgData",bbNetMsgData );
- }
- bool multiplay_create(){
- recv_buff_sz=send_buff_sz=1024;
- recv_buff=d_new char[recv_buff_sz];
- send_buff=d_new char[send_buff_sz];
- multiplay_setup_create();
- return true;
- }
- bool multiplay_destroy(){
- bbStopNetGame();
- multiplay_setup_destroy();
- delete[] recv_buff;recv_buff=0;
- delete[] send_buff;send_buff=0;
- return true;
- }
- static int startGame( int n ){
- clearPlayers();
- if( !n ) return 0;
- if( dirPlay->EnumPlayers( 0,enumPlayer,0,0 )>=0 ){
- host=n==2;
- return n;
- }
- multiplay_setup_close();
- return 0;
- }
- int bbStartNetGame(){
- if( dirPlay ){
- RTEX( "Multiplayer game already started" );
- }
- return startGame( multiplay_setup_open() );
- }
- int bbHostNetGame( BBStr *name ){
- if( dirPlay ){
- RTEX( "Multiplayer game already started" );
- }
- string n=*name;delete name;
- return startGame( multiplay_setup_host( n ) );
- }
- int bbJoinNetGame( BBStr *name,BBStr *address ){
- if( dirPlay ){
- RTEX( "Multiplayer game already started" );
- }
- string n=*name,a=*address;delete name;delete address;
- return startGame( multiplay_setup_join( n,a ) );
- }
- void bbStopNetGame(){
- multiplay_setup_close();
- clearPlayers();
- }
- DPID bbCreateNetPlayer( BBStr *nm ){
- chk();
- string t=*nm;
- string t0=t+'\0';
- delete nm;
- DPID id;
- DPNAME name;
- memset( &name,0,sizeof( name ) );
- name.dwSize=sizeof(name);name.lpszShortNameA=(char*)t0.data();
- if( dirPlay->CreatePlayer( &id,&name,0,0,0,0 )<0 ) return 0;
- Player *p=d_new Player( id,t,false );
- if( players.size()==1 ){
- if( dirPlay->EnumPlayers( 0,enumPlayer,0,0 )<0 ){
- dirPlay->DestroyPlayer( id );
- delete p;
- return 0;
- }
- }
- return id;
- }
- void bbDeleteNetPlayer( DPID player ){
- chk();
- if( Player *p=findPlayer( player ) ){
- dirPlay->DestroyPlayer( player );
- delete p;
- }
- }
- BBStr *bbNetPlayerName( DPID player ){
- if( !player ) return d_new BBStr( "<all>" );
- Player *p=findPlayer( player );
- return d_new BBStr( p ? p->name : "<unknown>" );
- }
- int bbNetPlayerLocal( DPID player ){
- if( Player *p=findPlayer( player ) ) return p->remote ? 0 : 1;
- return 0;
- }
- int bbRecvNetMsg(){
- chk();
- msg_type=0;
- msg_data.resize(0);
- msg_from=DPID_UNKNOWN;msg_to=DPID_ALLPLAYERS;
- while( !msg_type ){
- if( new_players.size() ){
- msg_from=new_players.front()->id;
- new_players.pop_front();
- msg_type=100;
- return 1;
- }
- DPID from,to;
- DWORD sz=recv_buff_sz;
- int n=dirPlay->Receive( &from,&to,0,recv_buff,&sz );
- if( n==DPERR_BUFFERTOOSMALL ){
- sz=recv_buff_sz=sz/2+sz;
- delete[] recv_buff;recv_buff=d_new char[recv_buff_sz];
- n=dirPlay->Receive( &from,&to,0,recv_buff,&sz );
- }
- if( n!=DP_OK ) return 0;
- if( from==DPID_SYSMSG ){
- switch( *(DWORD*)recv_buff ){
- case DPSYS_CREATEPLAYERORGROUP:
- if( DPMSG_CREATEPLAYERORGROUP *msg=(DPMSG_CREATEPLAYERORGROUP*)recv_buff ){
- if( findPlayer( from=msg->dpId ) ) continue;
- d_new Player( from,string( msg->dpnName.lpszShortNameA ),true );
- continue;
- }
- break;
- case DPSYS_DESTROYPLAYERORGROUP:
- if( DPMSG_DESTROYPLAYERORGROUP *msg=(DPMSG_DESTROYPLAYERORGROUP*)recv_buff ){
- Player *p=findPlayer( msg->dpId );if( !p ) continue;
- delete p;msg_from=msg->dpId;msg_type=101;
- }
- break;
- case DPSYS_HOST:
- if( !host ){
- host=true;msg_type=102;
- }
- break;
- case DPSYS_SESSIONLOST:
- msg_type=200;
- break;
- }
- }else{
- bbMsg *m=(bbMsg*)recv_buff;
- Player *p=findPlayer( m->from );
- if( p && !p->remote ) continue;
- msg_data=string( (char*)(m+1),sz-sizeof(bbMsg) );
- msg_from=m->from;msg_to=m->to;
- msg_type=m->type;
- }
- }
- return 1;
- }
- int bbNetMsgType(){
- return msg_type;
- }
- BBStr *bbNetMsgData(){
- return d_new BBStr( msg_data );
- }
- DPID bbNetMsgFrom(){
- return msg_from;
- }
- DPID bbNetMsgTo(){
- return msg_to;
- }
- int bbSendNetMsg( int type,BBStr *msg,DPID from,DPID to,int reliable ){
- chk();
- int sz=msg->size()+sizeof(bbMsg);
- if( sz>send_buff_sz ){
- send_buff_sz=sz/2+sz;
- delete send_buff;send_buff=d_new char[send_buff_sz];
- }
- bbMsg *m=(bbMsg*)send_buff;
- m->type=type;m->from=from;m->to=to;
- memcpy( m+1,msg->data(),msg->size() );
- if( !to ) to=DPID_ALLPLAYERS;
- int n=dirPlay->Send( from,to,reliable ? DPSEND_GUARANTEED : 0,send_buff,sz );
- delete msg;
- return n>=0;
- }
|