Um mal ein wenig auf das Multiplayerscripting einzugehen, versuch ich hier mal das ganze ein wenig zu erläutern.
Grundlagen:
Nachfolgend mal grundlegende Befehle um etwas zu synchronisieren.
Senden
publicVariable
Funktion: Sendet den Inhalt einer Variable an alle (Server + Client).
Syntax: publicVariable "Variable";
Wichtig: Die Variable muß in "" gesetzt werden als String
Hinweis: Löst den publicVariableEventHandler nicht auf dem Rechner aus, der diesen Befehl aufruft !
publicVariableClient
Funktion: Sendet den Inhalt einer Variable an eine bestimmten Client (nur auf dem Server ausführbar)
Syntax: clientID publicVariableClient "Variable";
Wichtig: Die Variable muß in "" gesetzt werden als String
Hinweis: Löst den publicVariableEventHandler nicht auf dem Rechner aus, der diesen Befehl aufruft !
clientID: Gibt die einzigartige ID des Besitzers eines Objektes auf dem Server zurück (lokal und global-Thematik) und läßt sich mit dem Befehl owner ermitteln
Syntax: _clientID = owner <object>;
Wenn man den Befehl (Serverseitig) auf den Charachter eines Spielers anwendet, gibt der Befehl die clientID des Spielers zurück (Zahl).
Funktioniert auch bei Objekten die auf einem Client gespawnt wurden, da sie dort lokal sind.(Was sich allerdings auch wieder ändern kann. (Siehe lokal/global)
<object> kann hierbei alles sein was als Objekt definiert ist wie z.B. Fahrzeuge, Einheiten, etc.
publicVariableServer
Funktion: Sendet den Inhalt einer Variable nur an den Server. (macht nur auf einem Client Sinn).
Syntax: publicVariableServer "Variable";
Wichtig: Die Variable muß in "" gesetzt werden als String
Hinweis: Löst den publicVariableEventHandler nicht auf dem Rechner aus, der diesen Befehl aufruft !
Gleiches Prinzip wie bei der Client-Variante, jedoch vom Client in Richtung Server.
Zusammenfassung: mit den Public-Befehlen lassen sich grundsätzlich Variablen übermitteln und mit der Client- bzw. Server-Variante gar gezielt, was den Bandbreitenverbrauch etwas schont.
Mit der Nachfolgenden Funktion habt ihr noch die Möglichkeit "Aktionen" auf dem Client/Sevrer ausführen zu lassen.
Empfang
addPublicVariableEventHandler
Funktion: Der <Code> wird ausgeführt sobald sich die Variable ändert und per publicVariable-Befehl gesendet wurde.
Syntax: "Variable" addPublicVariableEventHandler { <Code> };
Wichtig: Die Variable muß in "" gesetzt werden als String
Mit diesem Befehl lassen sich z.B. Wetter, Tageszeiten, usw. recht gut im MP synchronisieren.
Funktionen
Funktionen sind äußerst nützlich um die Bandbreite zu reduzieren, die man mit den publicVariable-Befehlen benutzt und reduziert somit den lag bei exzessiver Benutzung.
Wie man eine Funktion erstellt/definiert ist im Grunde recht simpel.
Beispiel globale Funktion (d.h. läßt sich immer wieder aufrufen):
In die {} Klammern schreibt ihr dann die Funktion.
Beispiel lokale Funktion (d.h. läßt sich nur innerhalb eines Scripts aufrufen und ist nach dem Ende des Scripts nicht mehr aufrufbar):
In die {} Klammern schreibt ihr dann die Funktion.
- Lokale Funktionen und Variablen fangen immer mit einem Unterstrich an und lassen sich nur innerhalb eines Scripts verwenden.
- Funktionen lassen sich mit call oder spawn aufrufen.
- call kann Werte zurück geben. Ruft man in einem Sctipt per call eine Funktion auf, so wartet die das Script bis die Funktion beendet ist.
- spawn ist quasi ein fire&forget-Aufruf. Script wartet nicht auf das Ende der Funktion
Nu mal zum praktischen Teil:
Beispiel: Tageszeit auf allen Clients mit dem Server synchronisieren:
initPlayerLocal.sqf
GT_fnc_syncDate = { _syncDate = _this; setDate _syncDate;};"GT_syncDate" addPublicVariableEventHandler { (_this select 1) call GT_fnc_syncDate; };
Diese Script wird auf jedem Client ausgeführt wenn er dem Server beitritt.
Hier wird 1. die Funktion GT_fnc_syncDate definiert und 2. ein EventHandler für die Variable GT_syncDate zugewiesen, d.h. jedes mal wenn die Variable per publicVariable-Befehl gesendet wird ruft der Client die Funktion GT_fnc_syncDate auf.
(_this select 0) -> Übergibt den Namen der Variable(wird hier aber nicht gebraucht)
(_this select 1) -> Übergibt den Inhalt der Variable und wird in der Funktion mit _this abgerufen.
initServer.sqf
Dieses Script wird beim Missionsstart nur vom Server ausgeführt und startet die Datei server_cycle.sqf.
server_cycle.sqf
while(true) DO {... - erstellt eine Endlos-Schleife
sleep (60*10); - Wartet 10 Minuten bevor es weiter geht.
GT_syncDate = date; - setzt die Variable auf das aktuelle Datum
publicVariable "GT_syncDate"; - publiziert die Variable an alle Clients
An dieser Stelle funktioniert es schon mal grundsätzlich die Zeit alle 10 Minuten zu synchronisieren, jedoch wenn ein Spieler dem laufenden Spiel (Join In Progress) beitritt, wird bei ihm erst die Zeit synchronisiert, wenn der Server cycle von 10 Minuten durch ist, was dazu führen kann dass er bis zu 10 Minuten nicht zur gleichen Tageszeit spielt. Um das zu umgehen erstellen wir noch ein weiteres Script, was die JIP-Spieler zusätzlich synchronisiert:
initPlayerServer.sqf
_playerObj = _this select 0; //mit select 0 erhaltet ihr bei diesem Script die Spielerfigur
waituntil{alive _playerObj}; //wartet bis der Spieler gespawnt ist
_clientID owner _playerObj; //ermittelt die client ID
GT_syncDate = date;
_clientID publicVariableClient "GT_syncDate"; //Der JIP-Spieler wird jetzt synchronisiert
initServer.sqf
intiPlayerLocal.sqf
und initServer.sqf sind sogenannte Event-Scripts, welche Variablen, Objekte, etc. über _this abrufbar sind könnt ihr hier nachlesen.