123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629 |
- #include "Spiel.h"
- #include <Zeit.h>
- #ifdef WIN32
- #include "..\..\Datenbank\Datenbank.h"
- #include "..\SpielServer.h"
- #include "Reader\KartenLeser.h"
- #else
- #include "Datenbank.h"
- #include "SpielServer.h"
- #include "KartenLeser.h"
- #include <unistd.h>
- #define Sleep( x ) usleep( (x) * 1000 )
- #include <dlfcn.h>
- #define LoadLibrary( x ) dlopen( (x), RTLD_LAZY )
- #define GetProcAddress dlsym
- #define FreeLibrary dlclose
- #endif
- typedef SpielKlasse*( *DllStart )( );
- // Inhalt der Spiel Klasse aus Spiel.h
- // Konstruktor
- Spiel::Spiel( int id, SpielServer *ss )
- : Thread()
- {
- this->ss = ss;
- this->id = id;
- klients = new RCArray< SSKlient >();
- sts = new SpielerTeamStruktur();
- accounts = new Array< int >();
- spielerNummern = new Array< int >();
- status = new Array< int >();
- prozent = new Array< int >();
- teamAuswahlFertig = new Array< bool >();
- spiel = 0;
- state = 0;
- spielerAnzahl = 0;
- karte = 0;
- spielDll = 0;
- statistik = 0;
- ref = 1;
- }
- // Destruktor
- Spiel::~Spiel()
- {
- klients->release();
- sts->release();
- accounts->release();
- spielerNummern->release();
- status->release();
- prozent->release();
- teamAuswahlFertig->release();
- if( spiel )
- spiel->release();
- if( statistik )
- statistik->release();
- if( spielDll )
- FreeLibrary( spielDll );
- ss->release();
- }
- int Spiel::findFreeTeam()
- {
- int free = 0;
- int teamIndex = 0;
- int teamSize = sts->teamSize->get( teamIndex );
- double max = 0;
- Array< int > teams;
- for( int i = 0; i < sts->spielerAnzahl; i++ ) // suche nach teams die prozentual am wenigsten voll sind
- {
- bool used = 0;
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- if( spielerNummern->hat( j ) && spielerNummern->get( j ) == i + 1 )
- used = 1;
- }
- if( !used )
- free++;
- teamSize--;
- if( !teamSize )
- {
- double teamVal = (double)free / sts->teamSize->get( teamIndex );
- if( teamVal > max )
- {
- teams.leeren();
- max = teamVal;
- }
- if( teamVal >= max )
- teams.add( teamIndex );
- free = 0;
- if( !sts->teamSize->hat( ++teamIndex ) )
- break;
- else
- teamSize = sts->teamSize->get( teamIndex );
- }
- } // suche aus den teams eines zufällig aus
- double randomVal = rand() / ( (double)RAND_MAX + 1 );
- double diff = 1.0 / teams.getEintragAnzahl();
- teamIndex = -1;
- while( randomVal >= 0 )
- {
- randomVal -= diff;
- teamIndex++;
- }
- if( teams.hat( teamIndex ) )
- return teams.get( teamIndex );
- else
- return teams.get( 0 );
- }
- void Spiel::teamAusgleich()
- {
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- int sNum = spielerNummern->hat( i ) ? spielerNummern->get( i ) : 0;
- if( !sNum )
- {
- int team = findFreeTeam();
- for( int j = 0; j < team; j++ )
- sNum += sts->teamSize->get( j );
- while( true )
- {
- sNum++;
- bool gefunden = 0;
- for( int k = 0; k < spielerAnzahl; k++ )
- {
- if( spielerNummern->hat( k ) && spielerNummern->get( k ) == sNum )
- {
- gefunden = 1;
- break;
- }
- }
- if( !gefunden )
- break;
- }
- spielerNummern->set( sNum, i );
- }
- }
- }
- // nicht constant
- void Spiel::setAccounts( int anzahl, Array< int > *zAccounts )
- {
- for( int i = 0; i < anzahl; i++ )
- accounts->set( zAccounts->hat( i ) ? zAccounts->get( i ) : 0, i );
- spielerAnzahl = anzahl;
- }
- void Spiel::setKlients( int anzahl, RCArray< SSKlient > *zKlients )
- {
- for( int i = 0; i < anzahl; i++ )
- klients->set( zKlients->get( i ), i );
- }
- void Spiel::setKarteId( int karteId )
- {
- karte = karteId;
- KartenLeser *reader = new KartenLeser( id, karte, ss->getThis() );
- reader->ladeSpielerTeamStruktur( sts );
- reader->release();
- start();
- }
- bool Spiel::klientVerbunden( SSKlient *klient )
- {
- int accId = klient->getAccountId();
- bool ret = 0;
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- if( accounts->hat( i ) && accounts->get( i ) == accId )
- {
- if( state == 1 )
- {
- klient->erstellungInitialisierung( sts );
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- if( accounts->hat( j ) && accounts->get( j ) != accId )
- {
- SSKlient *tmp = klients->z( j );
- tmp->erstellungAddSpieler( accId );
- klient->erstellungAddSpieler( accounts->get( j ) );
- if( spielerNummern->hat( j ) )
- klient->erstellungSpielerTeam( accounts->get( j ), spielerNummern->get( j ) );
- }
- }
- }
- if( state == 5 && spiel )
- spiel->klientOnline( klient->getAccountId(), klient );
- klients->set( klient, i );
- status->set( 1, i );
- klient->setSpiel( this );
- ret = 1;
- break;
- }
- }
- if( !ret )
- klient->release();
- return ret;
- }
- bool Spiel::klientWechseltTeam( int accountId, int team )
- {
- if( state != 1 )
- return 0;
- if( team == 0 )
- {
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- if( accounts->hat( i ) && accounts->get( i ) == accountId )
- spielerNummern->set( 0, i );
- SSKlient *tmp = klients->z( i );
- if( tmp )
- tmp->erstellungSpielerTeam( accountId, 0 );
- }
- return 1;
- }
- int von = 1;
- for( int i = 0; i < team - 1; i++ )
- {
- if( sts->teamSize->hat( i ) )
- von += sts->teamSize->get( i );
- }
- int bis = von + ( sts->teamSize->hat( team - 1 ) ? sts->teamSize->get( team - 1 ) : 0 );
- for( int i = von; i < bis; i++ )
- {
- bool verwendet = 0;
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- if( spielerNummern->hat( j ) && spielerNummern->get( j ) == i )
- {
- verwendet = 1;
- break;
- }
- }
- if( !verwendet )
- {
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- if( accounts->hat( j ) && accounts->get( j ) == accountId )
- spielerNummern->set( i, j );
- SSKlient *tmp = klients->z( j );
- if( tmp )
- tmp->erstellungSpielerTeam( accountId, i );
- }
- return 1;
- }
- }
- return 0;
- }
- bool Spiel::chatNachricht( char *nachricht )
- {
- if( state != 1 )
- return 0;
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- SSKlient *tmp = klients->z( i );
- if( tmp )
- tmp->erstellungChatNachricht( nachricht );
- }
- return 1;
- }
- bool Spiel::klientGetrennt( SSKlient *zKlient )
- {
- int accId = zKlient->getAccountId();
- bool ret = 0;
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- if( accounts->hat( i ) && accounts->get( i ) == accId )
- {
- if( status->hat( i ) && status->get( i ) != 0 )
- {
- if( state == 1 )
- {
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- if( accounts->hat( j ) && accounts->get( j ) != accId )
- {
- SSKlient *tmp = klients->z( j );
- tmp->erstellungRemoveSpieler( accId );
- }
- }
- }
- if( state == 5 && spiel )
- spiel->klientOffline( zKlient->getAccountId() );
- if( state == 6 )
- {
- if( statistik )
- statistik->klientOffline( zKlient->getAccountId() );
- }
- zKlient->setSpielErstellt( 0 );
- spielerNummern->set( 0, i );
- status->set( 0, i );
- klients->set( 0, i );
- ret = 1;
- }
- break;
- }
- }
- return ret;
- }
- bool Spiel::klientTeamAuswahlFertig( int accountId )
- {
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- if( accounts->hat( i ) && accounts->get( i ) == accountId )
- {
- teamAuswahlFertig->set( 1, i );
- return 1;
- }
- }
- return 0;
- }
- bool Spiel::klientBereitZumLaden( int accountId )
- {
- if( state != 2 )
- return 0;
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- if( accounts->hat( i ) && accounts->get( i ) == accountId )
- {
- status->set( 2, i );
- return 1;
- }
- }
- return 0;
- }
- bool Spiel::klientSpielLadenProzent( int accountId, int prozent )
- {
- if( state != 3 && state != 2 )
- return 0;
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- if( accounts->hat( i ) && accounts->get( i ) == accountId )
- {
- this->prozent->set( prozent, i );
- return 1;
- }
- }
- return 0;
- }
- bool Spiel::klientBereitZumSpiel( int accountId )
- {
- if( state != 4 )
- return 0;
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- if( accounts->hat( i ) && accounts->get( i ) == accountId )
- {
- status->set( 3, i );
- return 1;
- }
- }
- return 0;
- }
- bool Spiel::spielNachricht( int accountId, int len, char *bytes )
- {
- if( state != 5 )
- return 0;
- if( spiel )
- {
- spiel->nachricht( accountId, len, bytes );
- return 1;
- }
- return 0;
- }
- bool Spiel::statistikNachricht( int accountId, int len, char *bytes )
- {
- if( state != 6 )
- return 0;
- if( statistik )
- {
- statistik->statistikAnfrage( accountId, (short)len, bytes );
- return 1;
- }
- return 0;
- }
- void Spiel::thread()
- {
- // Klients aktualisieren
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- SSKlient *tmp = klients->z( i );
- if( tmp )
- {
- tmp->setSpielErstellt( 0 );
- tmp->setSpiel( this );
- }
- }
- // Vortsetzung senden
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- SSKlient *tmp = klients->z( i );
- if( tmp )
- tmp->erstellungInitialisierung( sts );
- }
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- SSKlient *tmp = klients->z( i );
- if( tmp )
- tmp->erstellungFortsetzen();
- }
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- SSKlient *tmp = klients->z( i );
- if( tmp )
- {
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- if( accounts->hat( j ) )
- tmp->erstellungAddSpieler( accounts->get( j ) );
- }
- }
- }
- // warten bis alle ein Team gewählt haben
- double time = 0;
- state = 1;
- ZeitMesser *zeit = new ZeitMesser();
- while( time < 40 )
- {
- zeit->messungStart();
- Sleep( 100 );
- char verbleibend = (char)( 40 - (char)time );
- bool weiter = 1;
- for( int i = 0; i < spielerAnzahl; i++ )
- weiter &= teamAuswahlFertig->hat( i ) && teamAuswahlFertig->get( i );
- if( verbleibend < 0 || weiter )
- {
- verbleibend = 0;
- time = 40;
- }
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- SSKlient *tmp = klients->z( i );
- if( tmp )
- tmp->zeitVerbleibend( verbleibend );
- }
- zeit->messungEnde();
- time += zeit->getSekunden();
- } // Spielernummern Aufteilen
- zeit->release();
- state = 2;
- teamAusgleich();
- Array< int > *teams = new Array< int >();
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- int sNum = spielerNummern->hat( i ) ? spielerNummern->get( i ) : 0;
- int tg = 1;
- for( int j = 0; j < sts->teamAnzahl; j++ )
- {
- tg += sts->teamSize->hat( j ) ? sts->teamSize->get( j ) : 0;
- if( sNum < tg )
- {
- teams->set( j, i );
- break;
- }
- }
- }
- ss->zDB()->spielSetTeams( id, spielerAnzahl, accounts, teams );
- ss->zDB()->spielSetSpielerNummern( id, spielerAnzahl, accounts, spielerNummern );
- teams->release();
- // Fortsetzung senden
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- SSKlient *tmp = klients->z( i );
- if( tmp )
- tmp->spielLadenBeginn();
- }
- // Auf bereitschaft warten
- while( 1 )
- {
- Sleep( 100 );
- bool br = 1;
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- if( klients->z( i ) )
- br = br && status->hat( i ) && status->get( i ) == 2;
- }
- if( br )
- break;
- } // Spieler hinzufügen
- for( int i = 0; i < spielerAnzahl; i++ )
- spielerNummern->set( ( spielerNummern->hat( i ) ? spielerNummern->get( i ) : 0 ) - 1, i );
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- SSKlient *tmp = klients->z( i );
- if( tmp )
- {
- for( int j = 0; j < spielerAnzahl; j++ )
- tmp->spielLadenSpielerAdd( accounts->hat( j ) ? accounts->get( j ) : 0, spielerNummern->hat( j ) ? spielerNummern->get( j ) : 0 );
- }
- }
- state = 3;
- // Warten auf laden
- while( 1 )
- {
- Sleep( 1000 );
- bool br = 1;
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- SSKlient *tmp = klients->z( i );
- if( tmp )
- {
- int ping = (int)( tmp->ping() * 1000 + 0.5 );
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- SSKlient *k = klients->z( j );
- if( k )
- {
- k->spielLadenSetSpielerPing( accounts->hat( i ) ? accounts->get( i ) : 0, ping );
- k->spielLadenSetSpielerProzent( accounts->hat( i ) ? accounts->get( i ) : 0, prozent->hat( i ) ? prozent->get( i ) : 0 );
- }
- }
- br = br && prozent->hat( i ) && prozent->get( i ) == 100;
- }
- }
- if( br )
- break;
- }
- state = 4;
- // Sende Fortsetzung
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- SSKlient *tmp = klients->z( i );
- if( tmp )
- tmp->spielLadenFertig();
- }
- // Spiel Initialisieren
- Text *pfad = new Text( ss->zInit()->zWert( "SpielePfad" )->getText() );
- pfad->append( "/" );
- pfad->append( ss->zDB()->getSpielArtId( karte ) );
- pfad->append( "/bin/game" );
- #ifdef WIN32
- pfad->append( ".dll" );
- #else
- pfad->append( ".so" );
- #endif
- spielDll = LoadLibrary( pfad->getText() );
- if( !spielDll )
- {
- // error
- }
- pfad->release();
- DllStart getSpielKlasse = (DllStart)GetProcAddress( spielDll, "getSpielKlasse" );
- if( !getSpielKlasse )
- {
- // error
- }
- spiel = getSpielKlasse();
- spiel->setPSQLK( ss->zDB()->getThis() );
- spiel->setSpielId( id );
- spiel->setKarteId( karte );
- Text tmp = ss->zInit()->zWert( "TempMapPfad" )->getText();
- tmp += "/";
- tmp += id;
- spiel->setTempPfad( tmp );
- spiel->setAccounts( spielerAnzahl, accounts );
- spiel->setKlients( spielerAnzahl, ( RCArray< SSKlientV >* )klients );
- spiel->setSpielerNummern( spielerAnzahl, spielerNummern );
- // auf klients warten
- while( 1 )
- {
- Sleep( 100 );
- bool br = 1;
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- if( klients->z( i ) )
- br = br && status->hat( i ) && status->get( i ) == 3;
- }
- if( br )
- break;
- }
- // Spiel starten
- state = 5;
- ss->zDB()->setSpielStatusIsRunning( id );
- spiel->run();
- // Spiel ist zuende
- state = 6;
- statistik = spiel->getStatistik();
- spiel = spiel->release();
- statistik->run();
- // Statistik ist zuende
- state = 7;
- statistik = statistik->release();
- FreeLibrary( spielDll );
- spielDll = 0;
- DateiRemove( tmp );
- ss->removeSpiel( id ); // delete this
- }
- // constant
- int Spiel::getId() const
- {
- return id;
- }
- int Spiel::getSpielerNummer( int accountId ) const
- {
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- if( accounts->hat( i ) && accounts->get( i ) == accountId )
- return spielerNummern->hat( i ) ? spielerNummern->get( i ) : 0;
- }
- return 0;
- }
- // Reference Counting
- Spiel *Spiel::getThis()
- {
- ref++;
- return this;
- }
- Spiel *Spiel::release()
- {
- ref--;
- if( !ref )
- delete this;
- return 0;
- }
|