123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724 |
- #include "Spiel.h"
- #include <time.h>
- #include <DateiSystem.h>
- #include "Define.h"
- #include "SSKlient.h"
- #include "KartenLeser.h"
- #include "Statistik.h"
- #include "Team.h"
- #include "Laser.h"
- #include <M2Datei.h>
- #include <iostream>
- #ifdef WIN32
- #include <random>
- #else
- #include <math.h>
- #include <unistd.h>
- #include <stdlib.h>
- #define Sleep( x ) usleep( (x) * 1000 )
- #endif
- // Inhalt der Spiel Klasse aus Spiel.h
- // Konstruktor
- Spiel::Spiel()
- {
- zAccounts = 0;
- zKlients = 0;
- asteroids = new RCArray< Asteroid >();
- asteroidModels = new RCArray< Model2DData >();
- stat = new Statistik();
- teams = new RCArray< Team >();
- teamAnzahl = 0;
- spieler = new RCArray< Spieler >();
- shots = new RCArray< Laser >();
- objekte = new RCArray< SpielObjekt >();
- welt = new Welt2D();
- pixel = new RCArray< Pixel >();
- welt->setCircular( 1 );
- welt->setAirResistance( 0.001f );
- psqldb = 0;
- spielId = 0;
- karteId = 0;
- spielerAnzahl = 0;
- karte = 0;
- InitializeCriticalSection( &cs );
- sts = 0;
- log = 0;
- isRunning = 0;
- spielZeit = 0;
- ende = 1;
- nextSchussId = 1;
- nextAsteroid = 30;
- asteroidId = 0;
- pixelId = 0;
- ref = 1;
- }
- // Destruktor
- Spiel::~Spiel()
- {
- teams->release();
- stat->release();
- spieler->release();
- objekte->release();
- welt->release();
- asteroids->release();
- asteroidModels->release();
- if( psqldb )
- psqldb->release();
- if( karte )
- karte->release();
- if( sts )
- sts->release();
- pixel->release();
- DeleteCriticalSection( &cs );
- }
- // privat
- int Spiel::getTeamVonSpieler( int sNum )
- {
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- Spieler *tmp = spieler->z( i );
- if( tmp && tmp->getSpielerNummer() == sNum )
- return tmp->zTeam() ? tmp->zTeam()->id : 0;
- }
- return 0;
- }
- // nicht constant
- void Spiel::setPSQLK( SSDatenbankV *psqldb )
- {
- if( this->psqldb )
- this->psqldb->release();
- this->psqldb = psqldb;
- stat->setPSQLDB( psqldb->getThis() );
- }
- void Spiel::setSpielId( int id )
- {
- spielId = id;
- stat->setSpielId( id );
- }
- void Spiel::setKarteId( int karteId )
- {
- this->karteId = karteId;
- stat->setKarteId( karteId );
- }
- void Spiel::setTempPfad( char *pfad )
- {
- mapPfad = pfad;
- mapPfad += "/";
- }
- void Spiel::setAccounts( int anzahl, Array< int > *zAccounts )
- {
- this->zAccounts = zAccounts->getThis();
- spielerAnzahl = anzahl;
- }
- void Spiel::setKlients( int anzahl, RCArray< SSKlientV > *zKlients )
- {
- this->zKlients = zKlients->getThis();
- }
- void Spiel::setSpielerNummern( int anzahl, Array< int > *spielerNummern )
- {
- if( !sts )
- {
- sts = new SpielerTeamStruktur();
- KartenLeser *reader = new KartenLeser( karteId, psqldb->getThis(), mapPfad );
- reader->ladeSpielerTeamStruktur( sts );
- if( karte )
- karte->release();
- karte = reader->ladeKarte( sts );
- reader->release();
- for( int i = 0; i < sts->teamAnzahl; i++ )
- teams->set( karte->createTeam( i ), i );
- stat->setTeamNamen( sts->teamName->getThis() );
- int objektAnzahl = karte->getObjektAnzahl();
- for( int i = 0; i < objektAnzahl; i++ )
- {
- SpielObjekt *obj = karte->createObjekt( i );
- welt->addObject( obj->getThis() );
- objekte->set( obj, i );
- }
- welt->setSize( karte->getSize().x, karte->getSize().y );
- welt->setSize( 1 );
- }
- for( int i = 0; i < anzahl; i++ )
- {
- Spieler *tmp = karte->createSpieler( spielerNummern->get( i ) );
- if( tmp )
- {
- int team = 0;
- int von = 0;
- int bis = 0;
- for( int j = 0; j < sts->teamAnzahl; j++ )
- {
- bis = von + ( sts->teamSize->hat( j ) ? sts->teamSize->get( j ) : 0 );
- if( tmp->getSpielerNummer() >= von && tmp->getSpielerNummer() < bis )
- {
- team = j;
- break;
- }
- von = bis;
- }
- tmp->setTeam( teams->get( team ) );
- teams->z( team )->spieler->add( tmp );
- }
- welt->addObject( tmp->getThis() );
- spieler->set( tmp, i );
- }
- for( int i = 0; i < anzahl; i++ )
- spieler->z( i )->setAccountId( zAccounts->hat( i ) ? zAccounts->get( i ) : 0 );
- for( int i = 0; i < anzahl; i++ )
- spieler->z( i )->setKlient( new Klient( zKlients->get( i ) ) );
- stat->setSpieler( spielerAnzahl, spieler );
- zAccounts = zAccounts->release();
- zKlients = zKlients->release();
- teamAnzahl = 0;
- for( int i = 0; i < sts->teamAnzahl; i++ )
- if( teams->z( i )->spieler->getEintragAnzahl() )
- teamAnzahl++;
- }
- void Spiel::klientOffline( int accountId )
- {
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- if( spieler->z( i )->getAccountId() == accountId )
- spieler->z( i )->offline();
- }
- }
- void Spiel::klientOnline( int accountId, SSKlientV *zKlient )
- {
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- if( spieler->z( i )->getAccountId() == accountId )
- {
- EnterCriticalSection( &cs );
- Spieler *s = spieler->z( i );
- s->online( zKlient );
- Klient *tmp = spieler->z( i )->zKlient();
- tmp->sendeSpielerNummer( s->getSpielerNummer(), 0 );
- //--------------------------
- LeaveCriticalSection( &cs );
- }
- }
- }
- void Spiel::nachricht( int accountId, int len, char *bytes )
- {
- if( !isRunning || ende )
- return;
- EnterCriticalSection( &cs );
- if( ende )
- {
- LeaveCriticalSection( &cs );
- return;
- }
- char *msgBeg = bytes;
- int msgLen = len;
- int msgAccount = accountId;
- bool saveMSG = 1;
- len--;
- switch( *bytes )
- {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- Spieler *tmp = spieler->z( i );
- if( tmp && tmp->getAccountId() == accountId )
- {
- if( !tmp->istAmLeben() )
- break;
- if( !tmp->setTastataturStatus( (TastaturStatus)( (int)( *bytes ) / 2 ), ( (int)( *bytes ) % 2 ) == 0 ) )
- {
- saveMSG = 0;
- break;
- }
- if( *bytes != 6 && *bytes != 7 )
- {
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- Spieler *s = spieler->z( j );
- if( s && s->zKlient() )
- s->zKlient()->sendeTastaturStatus( tmp->getSpielerNummer(), (TastaturStatus)( (int)( *bytes ) / 2 ), ( (int)( *bytes ) % 2 ) == 0, spielZeit );
- }
- }
- break;
- }
- }
- break;
- case 8: // chat Nachricht
- if( 1 )
- {
- bytes++;
- Text *txt = psqldb->getAccountRufName( accountId );
- txt->append( ": " );
- txt->append( bytes, len );
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- Spieler *tmp = spieler->z( i );
- if( tmp && tmp->zKlient() )
- tmp->zKlient()->sendeChatNachricht( txt->getText(), spielZeit );
- }
- txt->release();
- len = 0;
- }
- break;
- case 9: // Skill verwendung
- if( 1 )
- {
- bytes++;
- char art = *bytes;
- len--;
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- Spieler *tmp = spieler->z( i );
- if( tmp && tmp->getAccountId() == accountId )
- {
- if( !tmp->istAmLeben() )
- break;
- if( !tmp->setSkill( art ) )
- {
- saveMSG = 0;
- break;
- }
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- Spieler *s = spieler->z( j );
- if( s && s->zKlient() )
- s->zKlient()->sendeSkillNachricht( tmp->getSpielerNummer(), art, spielZeit );
- }
- break;
- }
- }
- break;
- }
- break;
- default:
- saveMSG = 0;
- }
- if( len )
- {
- // error
- }
- if( log && log->istOffen() && saveMSG )
- {
- char c = 1;
- log->schreibe( &c, 1 );
- int spielerNum = 0;
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- Spieler *tmp = spieler->z( i );
- if( tmp && tmp->getAccountId() == msgAccount )
- {
- spielerNum = tmp->getSpielerNummer();
- break;
- }
- }
- log->schreibe( (char*)&spielerNum, 4 );
- short l = (short)msgLen;
- log->schreibe( (char*)&l, 2 );
- log->schreibe( msgBeg, l );
- }
- LeaveCriticalSection( &cs );
- }
- void Spiel::tick( double zeit )
- {
- // Objekte updaten
- welt->tick( zeit );
- // Spieler Updaten
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- Spieler *tmp = spieler->z( i );
- if( tmp )
- {
- if( tmp->doNeedWiederbelebung() )
- { // Wiederbelebung
- tmp->wiederbeleben();
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- Spieler *s = spieler->z( j );
- if( s )
- s->zKlient()->sendeWiederbelebung( tmp->getSpielerNummer(), spielZeit );
- }
- }
- }
- }
- // Schüsse Collision
- int anz = shots->getEintragAnzahl();
- for( int i = 0; i < anz; i++ )
- {
- Laser *tmp = shots->z( i );
- if( tmp )
- {
- if( tmp->getIntensity() <= 0 )
- { // Schuss existiert nicht mehr
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- Spieler *s = spieler->z( j );
- if( s )
- s->zKlient()->sendeTreffer( tmp->getId(), -1, spielZeit, 0, 0 );
- }
- welt->removeObject( tmp );
- shots->remove( i );
- anz--;
- i--;
- }
- else
- { // Schuss existiert noch
- int team = getTeamVonSpieler( tmp->getSpieler() );
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- Spieler *s = spieler->z( j );
- if( s && s->zTeam() && s->zTeam()->id != team && s->istTreffer( tmp->getPosition() ) )
- { // Treffer
- double intens = tmp->getIntensity() * ( ( tmp->getSpeed() - s->getSpeed() ).getLength() / 200 );
- bool kill = s->nimmSchaden( intens );
- if( tmp->getSpeed().getLengthSq() > 0 )
- s->impuls( tmp->getPosition() - tmp->getSpeed(), tmp->getSpeed() * 0.3f );
- float erf;
- int skillP;
- for( int k = 0; k < spielerAnzahl; k++ )
- {
- Spieler *sp = spieler->z( k );
- if( sp && sp->getSpielerNummer() == tmp->getSpieler() )
- {
- sp->machSchaden( intens, kill );
- erf = sp->getEp();
- skillP = sp->getSkillP();
- }
- }
- for( int k = 0; k < spielerAnzahl; k++ )
- {
- Spieler *sp = spieler->z( k );
- if( sp )
- sp->zKlient()->sendeTreffer( tmp->getId(), s->getSpielerNummer(), spielZeit, erf, skillP );
- if( kill && sp )
- sp->zKlient()->sendeTod( s->getSpielerNummer(), tmp->getSpieler(), spielZeit );
- }
- if( kill )
- {
- if( teams->z( team - 1 ) )
- teams->z( team - 1 )->punkte++;
- if( teams->z( team - 1 )->punkte == teams->z( team - 1 )->maxPunkte )
- ende = 1;
- }
- welt->removeObject( tmp );
- shots->remove( i );
- anz--;
- i--;
- break;
- }
- }
- int aAnz = asteroids->getEintragAnzahl();
- for( int j = 0; j < aAnz; j++ )
- {
- Asteroid *a = asteroids->z( j );
- Vertex pos;
- __int64 seed = randG.getSeed();
- double intens = tmp->getIntensity() * ( ( tmp->getSpeed() - a->getSpeed() ).getLength() / 200 );
- Asteroid *b = a->istTreffer( tmp, &randG, asteroidId, pos );
- if( b )
- {
- float erf;
- int skillP;
- for( int k = 0; k < spielerAnzahl; k++ )
- {
- Spieler *s = spieler->z( k );
- if( s && s->getSpielerNummer() == tmp->getSpieler() )
- {
- s->addTreffer( (float)intens );
- erf = s->getEp();
- skillP = s->getSkillP();
- }
- }
- for( int k = 0; k < spielerAnzahl; k++ )
- {
- Spieler *s = spieler->z( k );
- if( s )
- s->zKlient()->sendeAsteroidTreffer( a->getId(), b->getId(), tmp->getId(), pos, seed, spielZeit, erf, skillP );
- }
- welt->removeObject( tmp );
- shots->remove( i );
- if( b->getMasse() > intens * 50 )
- {
- asteroids->add( (Asteroid*)b->getThis() );
- welt->addObject( b );
- }
- else
- {
- Pixel *p = new Pixel( b->getPosition(), b->getSpeed(), b->getMasse() / 50, pixelId++ );
- welt->addObject( p->getThis() );
- pixel->add( p );
- for( int k = 0; k < spielerAnzahl; k++ )
- {
- Spieler *s = spieler->z( k );
- if( s )
- s->zKlient()->sendePixel( b->getId(), p->getId(), spielZeit );
- }
- b->release();
- }
- if( a->getMasse() < intens * 50 )
- {
- Pixel *p = new Pixel( a->getPosition(), a->getSpeed(), a->getMasse() / 50, pixelId++ );
- welt->addObject( p->getThis() );
- pixel->add( p );
- for( int k = 0; k < spielerAnzahl; k++ )
- {
- Spieler *s = spieler->z( k );
- if( s )
- s->zKlient()->sendePixel( a->getId(), p->getId(), spielZeit );
- }
- welt->removeObject( a );
- asteroids->remove( j-- );
- aAnz--;
- }
- }
- }
- }
- }
- }
- // Neue Schüsse hinzufügen
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- Spieler *tmp = spieler->z( i );
- if( tmp )
- {
- Laser *nL = tmp->getLaser( nextSchussId );
- if( nL )
- {
- nextSchussId++;
- welt->addObject( nL->getThis() );
- shots->add( nL );
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- if( spieler->z( j ) && spieler->z( j )->zKlient() )
- spieler->z( j )->zKlient()->sendeSchuss( nL->getId(), nL->getSpieler(), nL->getPosition(), nL->getSpeed(), nL->getIntensity(), spielZeit );
- }
- }
- }
- }
- // Asteroiden
- nextAsteroid -= zeit;
- if( nextAsteroid <= 0 )
- {
- nextAsteroid += 30 + (float)randG.rand() * 30;
- Vertex pos = Vertex( (float)randG.rand() * (float)welt->getWorldInfo().size.x, (float)randG.rand() * (float)welt->getWorldInfo().size.y );
- Vertex speed = Vertex( (float)randG.rand() * 100, (float)randG.rand() * 100 );
- float rot = 2 * (float)PI * (float)randG.rand();
- float rotS = (float)randG.rand();
- int index = (int)( (float)asteroidModels->getEintragAnzahl() * (float)randG.rand() );
- Asteroid *astr = new Asteroid( asteroidId++, pos, speed, rot, rotS, asteroidModels->get( index ) );
- asteroids->add( astr );
- welt->addObject( astr->getThis() );
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- if( spieler->z( j ) && spieler->z( j )->zKlient() )
- spieler->z( j )->zKlient()->sendeAsteroid( astr->getId(), pos, speed, rot, rotS, index, spielZeit );
- }
- }
- // Pixel
- int pixelAnz = pixel->getEintragAnzahl();
- for( int i = 0; i < pixelAnz; i++ )
- {
- Pixel *p = pixel->z( i );
- if( p->getEp() <= 0 )
- {
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- if( spieler->z( j ) && spieler->z( j )->zKlient() )
- spieler->z( j )->zKlient()->sendeEp( p->getId(), -1, spielZeit );
- }
- pixel->remove( i-- );
- welt->removeObject( p );
- pixelAnz--;
- }
- else
- {
- for( auto s = spieler->getIterator(); s; s++ )
- {
- if( s->istTreffer( p->getPosition() ) )
- {
- s->addEp( p->getEp() );
- for( int j = 0; j < spielerAnzahl; j++ )
- {
- if( spieler->z( j ) && spieler->z( j )->zKlient() )
- spieler->z( j )->zKlient()->sendeEp( p->getId(), s->getSpielerNummer(), spielZeit );
- }
- pixel->remove( i-- );
- welt->removeObject( p );
- pixelAnz--;
- break;
- }
- }
- }
- }
- }
- void Spiel::run()
- {
- Text *pfad = psqldb->getSpielPfad( karteId );
- if( pfad )
- pfad->append( "/" );
- pfad->append( "models/asteroids.m2" );
- M2Datei *aDat = new M2Datei();
- aDat->setPfadZ( pfad );
- aDat->leseDaten();
- int anz = aDat->getModelAnzahl();
- for( int i = 0; i < anz; i++ )
- {
- asteroidModels->add( aDat->ladeModel( aDat->zModelName( i )->getText() ) );
- }
- log = new Datei();
- pfad = new Text( "../spiel log/" );
- pfad->append( spielId );
- pfad->append( "/verlauf.ksggl" );
- log->setDatei( pfad );
- log->remove();
- log->erstellen();
- log->open( Datei::Style::schreiben );
- time_t t;
- time( &t );
- srand( (unsigned int)t );
- log->schreibe( (char*)&spielerAnzahl, 4 );
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- Spieler *tmp = spieler->z( i );
- if( tmp && tmp->zKlient() )
- {
- tmp->zKlient()->sendeInit( spieler, -1 );
- log->schreibe( (char*)&i, 4 );
- int sNum = tmp->getSpielerNummer();
- log->schreibe( (char*)&sNum, 4 );
- tmp->zKlient()->sendeSpielerNummer( sNum, -1 );
- int team = tmp->zTeam()->id;
- log->schreibe( (char*)&team, 4 );
- int farbe = tmp->getSpielerFarbe();
- log->schreibe( (char*)&farbe, 4 );
- farbe = tmp->zTeam()->farbe;
- log->schreibe( (char*)&farbe, 4 );
- Text *name = psqldb->getAccountRufName( tmp->getAccountId() );
- char len = (char)( name ? name->getLength() : 0 );
- log->schreibe( &len, 1 );
- if( len )
- log->schreibe( name->getText(), len );
- if( name )
- name->release();
- name = sts->teamName->z( team );
- len = (char)( name ? name->getLength() : 0 );
- log->schreibe( &len, 1 );
- if( len )
- log->schreibe( name->getText(), len );
- }
- }
- __int64 randSeed = randG.getSeed();
- log->schreibe( (char*)&randSeed, 8 );
- Array< char > spielerStatus;
- ZeitMesser *zeit = new ZeitMesser();
- zeit->messungStart();
- isRunning = 1;
- ende = 0;
- double ausgleich = 0;
- double sZ = 0;
- spielZeit = -1;
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- Spieler *tmp = spieler->z( i );
- if( tmp && tmp->zKlient() )
- tmp->zKlient()->sendeStart( spielZeit );
- }
- double rZeit = 0;
- while( !ende )
- {
- zeit->messungEnde();
- zeit->messungStart();
- double z = zeit->getSekunden();
- ausgleich += TICK - z;
- if( ausgleich > 0 )
- Sleep( (int)( ausgleich * 1000 ) );
- rZeit += z;
- while( sZ + TICK < rZeit && !ende )
- {
- EnterCriticalSection( &cs );
- sZ += TICK;
- spielZeit++;
- char c = 0;
- log->schreibe( &c, 1 );
- tick( TICK );
- LeaveCriticalSection( &cs );
- }
- }
- zeit->messungEnde();
- zeit->release();
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- if( spieler->z( i ) && spieler->z( i )->zKlient() )
- {
- if( spieler->z( i )->zTeam()->punkte < spieler->z( i )->zTeam()->maxPunkte )
- {
- spielerStatus.set( 1, i ); // Datenbank Verloren
- spieler->z( i )->zKlient()->sendeSpielEnde( 0, 0 );
- }
- else
- {
- spielerStatus.set( 2, i ); // Datenbank Gewonnen
- spieler->z( i )->zKlient()->sendeSpielEnde( 1, 0 );
- }
- }
- if( spieler->z( i ) && ( !spieler->z( i )->zKlient() || !spieler->z( i )->istOnline() ) )
- spielerStatus.set( 3, i );
- }
- if( teamAnzahl == 1 )
- psqldb->setSpielStatusBeendet( spielId, 6 );
- else
- psqldb->setSpielStatusBeendet( spielId, 5 );
- for( int i = 0; i < spielerAnzahl; i++ )
- {
- Spieler *tmp = spieler->z( i );
- if( tmp )
- {
- psqldb->setSpielSpielerStatus( spielId, tmp->getAccountId(), tmp->getPunkte(), spielerStatus.get( i ) );
- if( teamAnzahl > 1 )
- psqldb->addSpielerStatistik( tmp->getAccountId(), spielId );
- }
- }
- log->close();
- log = log->release();
- isRunning = 0;
- }
- // constant
- StatistikV *Spiel::getStatistik() const
- {
- return stat->getThis();
- }
- // Reference Counting
- SpielKlasse *Spiel::getThis()
- {
- ref++;
- return this;
- }
- SpielKlasse *Spiel::release()
- {
- ref--;
- if( !ref )
- delete this;
- return 0;
- }
|