Hallo,
in diesem Tutorial möchte ich erklären, wie die Limits in SA:MP zustande kommen und wie sie umgangen werden können.
Um Limits umgehen zu können, muss zunächst ihr Ursprung geklärt werden.
Viele Leute denken sich sicherlich, dass dies daran liegt, dass GTA: SA ein relativ altes Spiel ist und daher nur eine begrenzte Anzahl an Elementen unterstützt.
Diese Aussage ist nur zum einem sehr kleinen Teil der Fall:
Feste hardware-unabhängige Limits, wie sie in SA:MP der Fall sind, entstehen in der Programmierung hauptsächlich dann, wenn der Speicher statisch begrenzt wird.
Das bedeutet, dass Speicher für Elemente nicht dynamisch angefordert wird, sondern von vorne rein reserviert wird.
Als Ausweg und Einführung "dynamischer Limits" (also letztendlich keine Limits) kann Speicher dynamisch angefordert werden, also immer dann, wenn neuer Speicher gebraucht wird, also z.B., wenn ein neuer Spieler auf den Server kommt oder ein neues Objekt erstellt wurde.
Zur Veranschaulichung ein Sourcecodebeispiel aus SA:MP (Achtung: Pseudocode, aber exakt SA:MP 0.3z entsprechend):
CPlayerPool* pPlayerPool = (CPlayerPool *)operator new(0x184C0u); // Reservierung von 99 520 Bytes (knapp 100KiB) Speicher
if ( pPlayerPool )
this->m_pPlayerPool = CPlayerPool::CPlayerPool(pPlayerPool); // Klassenkonstruktor aufrufen (PlayerPool initialisieren)
pObjectPool = (CObjectPool *)operator new(0x3D37E0u); // Reservierung von 4 012 000 (knapp 4MiB) Speicher
if ( pObjectPool )
this->m_pObjectPool = CObjectPool::CObjectPool(pObjectPool); // Klassenkonstruktor aufrufen (ObjectPool initialisieren)
Innerhalb dieser Strukturen befinden sich dann weitere Arrays in einer Größe der Anzahl der Spieler, Objekte, etc.:
// Ausschnitt aus der Deklaration des Spieler-Pools
#define PLAYER_LIMIT 500 // Array-Größe auf 500 festlegen (= Limit)
class CPlayerPool
{
/* Irgendwas */
CPlayer* PlayerPointers[PLAYER_LIMIT];
int PlayerScoreData[PLAYER_LIMIT];
int PlayerMoneyData[PLAYER_LIMIT];
/* Noch mehr */
};
Alles anzeigen
Hier sieht man, dass, obwohl nur eine kleine Anzahl an Slots reserviert ist, viel Speicher benötigt wird, obwohl dieser überhaupt gar nicht genutzt wird.
Das bedeutet, dass nur mit einer Erhöhung der Konstante PLAYER_LIMIT das Limit erhöht wird, dafür aber auch viel mehr Speicher benötigt wird.
Heutzutage (und auch schon vor 10 Jahren) wird in C++-Büchern gelehrt, dass statt statischen Arrays (wie sie in SA:MP genutzt werden) dynamische Container genutzt werden sollten. Dadurch kann Speicher viel effektiver genutzt werden, sodass er nur angefordert wird, wenn er auch benötigt wird.
Wie schon grob angedeutet, gibt es im Wesentlichen 3 Möglichkeiten die lästigen Limits zu umgehen:
1.) Den SA:MP-Code nehmen und die Konstanten erhöhen.
Nachteil: Es wird noch mehr Speicher unnötig verschwendet, und die Ladezeiten des Servers werden um Jahrzehnte erhöht.
2.) Wie 1.) mit dem Unterschied, dass bestehende statische Strukturen in dynamische Container verwandelt werden:
Vorteil: Effektive Speichernutzung
Nachteil: Dies würde den Umfang eines SA:MP Updates sprengen und innerhalb von 4 Jahren nicht umsetzbar sein
3.) Zu MTA wechseln:
MTA wurde von Anfang an mit Nutzung dynamischer Strukturen konzipiert, sodass von seiten MTA gar keine Limits existieren.
Die einzige Limits sind die von GTA, die jedoch zu Großteilen durch Patching in dynamische Strukturen (wie 2.)/Patching der Größen (wie 1.) erhöht wurden.
Weitere positiver Nebeneffekt: MTA bietet eine Vielzahl an zusätzlichen Features und bessere Synchronisation
Nachteil: Verabschiedung von der tollen SA:MP Community
Mit freundlichen Grüßen