Workshop 3: Multizones


In diesem Workshop wird Ihnen erklärt, wie Sie große Welten wie in einem MMORPG in mehrere Zonen aufteilen können und zwischen den Zonen wechseln können. Dieses HowTo baut auf HowTo1 und dem Simple 3D Chat Tutorial auf.

Was sind Zonen


Zonen sind abgeschirmte Bereiche einer riesigen Spielumgebung. Normalerweise liegt jede Zone auf einem eigenen Server. Die riesige Spielwelt wird nun in mehrere kleinere Levels unterteilt und jedes Level wird einem Server zugeteilt.
Ein Beispiel: Eine Zone ist eine Stadt mit einer riesigen Stadtmauer rund herum. Von dieser kann man durch ein Tor in einen Außenbereich (z.B.) einen Hafen wechseln. Außerdem kann man durch einen Brunnen in eine geheime Höhle wechseln. Die Stadt, der Hafen und die geheime Höhle sind jeweils eigene Zonen.
Sobald man von einer Zone zur nächsten wechselt, wird die Verbindung zum einen Server unterbrochen und zum anderen Server hergestellt. Außerdem wird das neue Level, das der andere Server verwaltet, geladen.
Nun ist Ihnen sicherlich auch schon klar, warum Zonen verwendet werden: Mit Zonen kann man leicht den Datenverkehr aufteilen bzw. am Client sparen. Dadurch das Spieler, die in Zone A sind keine Daten von Spielern die in Zone B sind zugesendet bekommen, wird eine riesige Umgebung mit hunderten Spielern in mehrere kleinere Umgebungen mit jeweils wenigen Spielern aufgeteilt.

Neben den einzelnen Servern, die die Zonen verwalten, gibt es in MMORPGs auch noch einen Datenbankserver, der die Spielerdaten speichert und verwalten. Mit ANet kann man dies mit einem SQL Server realisieren. Per http_post() und PHP können Sie auf die Datenbank zugreifen. Zugriffe über PHP auf Datenbankserver sind meist sicherer als direkte Zugriffe.

Zonen erstellen


Wie weiter oben bereits gesagt wurde, ist eine Zone nichts anderes als ein Server mit einem Level. Also erstellen wir eine Zone wie folgend:

//Lite-C:
function init_zoneA()
{
level_load("zoneA.wmb");
wait(3);
enet_init_server(2300,32,"");
enet_set_level("zoneA.wmb");
}

function init_zoneB()
{
level_load("zoneB.wmb");
wait(3);
enet_init_server(2301,32,"");
enet_set_level("zoneB.wmb");
}

init_zoneA() lädt das Level der entsprechenden Zone und erstellt danach den Server. enet_set_level() teilt dem Server mit, welches Level geladen wurde. In der Realität wird jede Zone auf einem eigenen Rechner gestartet werden. Um das Testen und Arbeiten mit mehreren Zonen für uns zu vereinfachen, öffnen wir einfach pro Zone ein neues Fenster.
Wenn wir also 2 Zonen eröffnen möchten, starten wir unser Spiel und führen init_zoneA() aus. Danach öffnen wir es ein zweites Mal und führen in dem zweiten Fenster init_zoneB() aus. Sie müssen darauf achten, dass Sie die einzelnen Server mit unterschiedlichen Ports initialisieren, da pro Rechner jeder Port nur einmal für einen Server verwendet werden darf.

Zone beitreten/wechseln


Nun da wir wissen, wie wir Zonen erstellen sehen wir uns als nächstes an, wie man sich mit einer Zone verbinden kann bzw. wie man zwischen 2 Zonen wechseln kann:

//Lite-C:

function connection_astablished(var sender, char* msg, var length)
{
level_load(msg);
wait(3);
enet_ent_synchronize();
}

function synch_complete(var sender, char* msg, var length)
{
error("Connected with ZoneA!");
}
function zoneA_connect()
{
enet_clset_event(EVENT_CONNECTED, connection_astablished);
enet_clset_event(EVENT_SYNCHRONIZED, synch_complete);
enet_init_client("localhost",2300,"");
}

Der Code sollte bereits aus dem Simple 3D Chat Tutorial bekannt sein: Es wird ein Client erstellt, der sich mit einem am Localhost befindlichen Server über Port 2300 verbindet (das ist ZoneA in unserem Fall). Sobald die Verbindung mit dem Server hergestellt wurde, wird das Level geladen, dass am Server geladen wurde und danach wird eine Entitysynchronisierung gestartet. Sobal die Synchronisierung erfolgreich ausgeführt wurde, wird "Connected with ZoneA!" ausgegeben.
Wenn Sie sich mit ZoneB verbinden möchten, müssten Sie in unserem Fall einfach nur den Port von 2300 auf 2301 umändern. Würde sich ZoneB auf einen anderen Rechner befinden, müssten Sie die IP Adresse des Rechners verwenden.

Ok, wir wissen nun, wie man sich mit einer Zone verbindet. Wie wechselt man nun die Verbindung?

//Lite-C:
function disconnect()
{
enet_host_destroy();
level_load("");
wait(3);
}

Um nun ein Wechseln der Verbindung zu ermöglichen, benötigen wir eine weitere Funktion: disconnect(). Sie zerstört den aktuellen Client und lädt ein leeres Level damit alle laufende Entityfunktionen beendet werden. Statt enet_host_destroy sollten Sie lieber ein Event an den Server senden und dieser sollte per enet_disconnect_client die Verbindung unterbrechen. Der Nachteil von enet_host_destroy ist nämlich, dass der Client einfach zerstört wird und dem Server nicht mitgeteilt wird, dass die Verbindung unterbrochen wurde. Dadurch dauert es eine gewisse Zeit, bis der Server registriert hat, dass die Verbindung unterbrochen wurde.
Wenn wir nun von ZoneA in ZoneB wechseln wollen, rufen wir einfach disconnect() auf. Danach verbinden wir uns wieder wie im Beispiel oben.