123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684 |
- #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;
- }
- // 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;
- }
- while (!spielerNummern->hat(i))
- spielerNummern->add(0);
- spielerNummern->set(sNum, i);
- }
- }
- }
- // nicht constant
- void Spiel::setAccounts(int anzahl, Array< int >* zAccounts)
- {
- accounts->leeren();
- for (int i = 0; i < anzahl; i++)
- accounts->add(zAccounts->hat(i) ? zAccounts->get(i) : 0);
- spielerAnzahl = anzahl;
- }
- void Spiel::setKlients(int anzahl, RCArray< SSKlient >* zKlients)
- {
- klients->leeren();
- for (int i = 0; i < anzahl; i++)
- klients->add(zKlients->get(i));
- }
- void Spiel::setKarteId(int karteId)
- {
- karte = karteId;
- KartenLeser* reader = new KartenLeser(id, karte, dynamic_cast<SpielServer*>(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);
- while (!klients->hat(i))
- klients->add(0);
- klients->set(klient, i);
- while (!status->hat(i))
- status->add(0);
- 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)
- {
- while (!spielerNummern->hat(i))
- spielerNummern->add(0);
- 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)
- {
- while (!spielerNummern->hat(j))
- spielerNummern->add(0);
- spielerNummern->set(i, j);
- }
- SSKlient* tmp = klients->z(j);
- if (tmp)
- tmp->erstellungSpielerTeam(accountId, i);
- }
- return 1;
- }
- }
- return 0;
- }
- bool Spiel::chatNachricht(const 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);
- while (!spielerNummern->hat(i))
- spielerNummern->add(0);
- spielerNummern->set(0, i);
- while (!status->hat(i))
- status->add(0);
- status->set(0, i);
- while (!klients->hat(i))
- klients->add(0);
- 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)
- {
- while (!teamAuswahlFertig->hat(i))
- teamAuswahlFertig->add(0);
- 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)
- {
- while (!status->hat(i))
- status->add(0);
- 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)
- {
- while (!this->prozent->hat(i))
- this->prozent->add(0);
- 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)
- {
- while (!status->hat(i))
- status->add(0);
- 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)
- {
- while (!teams->hat(i))
- teams->add(0);
- 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)
- {
- char* err = dlerror();
- Text tmp = ss->zInit()->zWert("TempMapPfad")->getText();
- tmp += "/";
- tmp += id;
- DateiRemove(tmp);
- for (int i = 0; i < spielerAnzahl; i++)
- {
- SSKlient* tmp = klients->z(i);
- if (tmp)
- {
- tmp->setSpiel(0);
- tmp->errorZuKlientSende(Text("Fehler beim laden des Spiels: ").operator+(err));
- }
- }
- ss->zDB()->setSpielStatusBeendet(id, 4);
- ss->removeSpiel(id); // delete this
- return;
- }
- pfad->release();
- DllStart getSpielKlasse = (DllStart)GetProcAddress(spielDll, "getSpielKlasse");
- if (!getSpielKlasse)
- {
- FreeLibrary(spielDll);
- spielDll = 0;
- Text tmp = ss->zInit()->zWert("TempMapPfad")->getText();
- tmp += "/";
- tmp += id;
- DateiRemove(tmp);
- for (int i = 0; i < spielerAnzahl; i++)
- {
- SSKlient* tmp = klients->z(i);
- if (tmp)
- {
- tmp->setSpiel(0);
- tmp->errorZuKlientSende("Fehler beim laden des Spiels. Der Server kann das Spiel nicht finden.");
- }
- }
- ss->zDB()->setSpielStatusBeendet(id, 4);
- ss->removeSpiel(id); // delete this
- return;
- }
- spiel = getSpielKlasse();
- spiel->setPSQLK(dynamic_cast<SSDatenbankV*>(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 = (SpielKlasse*)spiel->release();
- statistik->run();
- // Statistik ist zuende
- state = 7;
- statistik = (StatistikV*)statistik->release();
- FreeLibrary(spielDll);
- spielDll = 0;
- DateiRemove(tmp);
- for (int i = 0; i < spielerAnzahl; i++)
- {
- SSKlient* tmp = klients->z(i);
- if (tmp)
- tmp->setSpiel(0);
- }
- 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;
- }
|