Zum Inhalt

Socket.IO

Verbinde adaptor:ex mit jeder Art von Webseite oder Web App die über eine Socket.IO Schnittstelle verfügt. Socket.IO erlaubt es in beide Richtungen zwischen APP und Server zu kommunizieren.

Mit dem Socket.IO Plugin kannst du beliebig viele Namespaces verbinden und Nachrichten über Rooms organisieren.

Das Socket.IO Plugin kann auch in ein eigenes Plugin integriert werden um Actions und Funktionalitäten für spezifische Web APPs anzupassen.

Einrichten

Füge das Socket.IO Plugin über Game -> Settings hinzu und erstelle einen oder mehrere socket.io Namespaces.

Über das Settings Menü kannst du weitere Einstellungs Optionen für den Namespace hinzufügen.

Wähle Settings unter settings aus und aktiviere die gewünschten Optionen

namespace

optional

Der Name des socketio namespace über den sich web clients verbinden können. Die namespace url besteht aus der adaptor:ex server url (z.B. localhost:8081), dem Game Namen, dem Namen des plugins (hier socketio) und diesem namespace Namen. Die vollständige URL der Verbindung sieht etwa so aus:

http://localhost:8081/TestGame/socketio/test_namespace

Gibst du keinen expliziten namespace Namen an, wird der Name des Namespace items als namespace name verwendet.

Die volle URl, über die sich der client verbinden kann, wird unter namespace url angegeben.

Die Namspace URLs werden nach erstellen des Namespace angezeigt

Die verfügbaren Basis URLs hängen von deinem Netzwerk und der adaptor:ex Server Konfiguration ab.

add meta data

optional

Wenn add meta data angewählt ist, werden alle Nachrichten, die mit diesem Namespace an den client gesendet werden mit info daten versehen.

Die folgenden properties werden hinzugefügt:

  • timestamp: Uhrzeit und Datum als unix timestamp, an dem die Nachricht gesendet wurde

  • message_id: eine eindeutige ID für die Nachricht

  • room: Der room, an den die Nachricht gesendet wurde

Die Nachricht selbst wird in der data property versendet.

Nachrichten, die so an den client gesendet werden sind immer js Objekte.

Eine Nachricht my message to the client im room mit der ID my_room mit zusätzlichen Metadaten könnte so aussehen:

{
  "data": "my message to the client",
  "timestamp": 1737027084827,
  "message_id": "mNeMIgMf",
  "room": "my_room"
}

level

optional

Level, das automatisch gestartet wird, wenn der Client eine Message über das Topic create sendet und einen neuen room erstellt.

level argument

optional

Gib den Namen für ein Level Argument, dass die Daten zum room enthält, der mit create neu erstellt wurde.

name

Der Level Argument name über den du im Level auf die room Daten zugreifen kannst.

type

Gibst du string als Datentyp an, enthält das Level Argument die room id.

Gibst du object als Datentyp an, enthält das Level Argument alle Daten die zum room gespeichert wurden.

Gibst du eine Data Collection als Datentyp an, wird mit create room ein neues Item in der entsprechenden Collection angelegt. Über das Level Argument kannst du dann auf das neu erstellte Item zugreifen.

intro als Level Name, TeamRoom als Level Argument Name und teams als type

room id pattern

optional

Ein string Format, das verwendet wird, wenn mit create ein neuer room mit automatischer id erstellt wird.

Gib unter length die Anzahl Zeichen an, die neu erstellte room ids haben werden. In characters kannst du alle Zeichen angeben, die beim automatischen Erstellen von room ids verwendet werden.

In diesem Beispiel werden room ids für diesen Namespace 5 stellige Zahlen:

length hat den Wert 5 und characters enthält die Ziffern 0-9

Rooms erstellen und beitreten

Namespaces im Socket.IO plugin bieten die Möglichkeit rooms über den client erstellen und beitreten zu lassen. Nachrichten, die in einem room ausgetauscht werden, werden nur von clients empfangen, die dem entsprechnden room über join beigetreten sind.

Folgende topics sind für diesen Zweck reserviert.

create

Erstellt einen neuen socket.io room. Die room id und ggf. weitere Eigenschaften werden im entsprechenden Namespace Item gespeichert.

Wenn für den Namespace ein level angegeben ist, wird mit create auch immer eine session des angegebenen Levels gestartet, wenn der room noch nicht existiert.

Wenn für den Namespace ein level mit level argument ist und level argument type ist eine data collection, wird zudem ein Data Item erstellt. Room Informationen werden dann in diesem Data Item statt des Namespace Items gespeichert.

Der client tritt automatisch dem neu erstellten room bei (join)

create gibt über socket.io callback oder emitWithAck einen Fehler zurück, wenn der room bereits existiert.

topic: create

message: Die room id und ggf. weitere Eigenschaften, die gespeichert werden sollen.

Ist message ein string, wird ein room mit der entsprechenden id angelegt. String message Beispiel:

my_room

Ist message ein Objekt werden zusätzlich zur id alle Eigenschaften des Objektes zum room gespeichert. Um eine eigene id zu vergeben muss die Nachricht eine id property enthalten. Objekt message Beispiel:

{
    id: "my_room",
    title: "My Room",
    color: "blue"
}

Ist message leer, oder wird existiert keine id property, wird eine automatische room id erstellt. Die Form der id kann über die Namespace Einstellung room id pattern festgelegt werden.

Die automatisch generierte room id wird über socket.io callback oder emitWithAck zurückgegeben.

returns: Gibt ein js object zurück, dass die room id enthält. Zum Beispiel:

{
    "id": "my_room"
}

join

Der client tritt dem angegebenen room bei. Wird der room in einer Socket.IO action verwendet, ist dieser client in die Kommunikation einbezogen.

join gibt über socket.io callback oder emitWithAck einen Fehler zurück, wenn der room nicht existiert.

topic: join

message: Die room id als string. Beispiel

my_room

returns: Gibt die room id und alle Daten, die mit dem room assoziiert sind zurück. Beispiel:

{
    id: "my_room",
    title: "My Room",
    color: "blue"
}

leave

Der client verlässt den angegebenen room wieder.

topic: leave

message: Die room id (string), des room der verlassen werden soll. Beispiel:

my_room

Sende message all um alle rooms zu verlassen.

rooms

Gibt eine Liste aller rooms zurück, denen der client beigetreten ist.

Mit der message all werden alle rooms zurückgegeben, die im Namespace existieren.

topic: rooms

message: Ist message leer, werden nur die rooms zurückgegeben denen der client mit join beigetreten ist. Mit

all

werden alle rooms zurückgegeben die im Namespace existieren.

Actions

Beispiel

Level File: socketio_example.json

HTML File: socketio_example.html

Öffne dein adaptor:ex Game und richte das Socket.IO Plugin mti einem Namespace ein (Einrichten).

Erstelle eine .html Datei HTML Webseite und füge die socket.io client library hinzu.

Zum Beispiel:

<html>
    <head>
        <title>adaptor:ex socket.io plugin example</title>
        <meta charset="utf-8">
    </head>

    <body>
    </body>
    <script src="https://cdn.socket.io/4.8.1/socket.io.min.js"></script>
    <script>
        console.log("Let's get started!")
    </script>
</html>

Kopiere die namespace url aus den Socket.IO Plugin settings (namespace) und erstelle eine Verbindung zu deinem Namespace im script deiner Webseite.

<script>
    console.log("Let's get started!")
    const socket = io("http://localhost:8081/Tutorial/socketio/my_app")
</script>

Nun kannst du die socket.io client library Funktionen Nutzen um Daten zwischen deiner Webseite und deinem adaptor:ex Game auszutauschen.

Eine Nachricht zur Webseite Senden

Teste die Verbindung indem du ein neues Level erstellst und eine Send Socketio Message auf die Stage ziehst.

Lasse room frei und gib ein topic und eine einfache message an.

Send Socket.IO Message hier mit topic: grretings und message Nice to meet you

Im script deiner Webseite füge die socket.on Funktion mit dem entsprechenden topic hinzu und nutze console.log um eingehende Nachrichten in die console zu schreiben.

<script>
    console.log("Let's get started!")
    const socket = io("http://localhost:8081/Tutorial/socketio/my_app")

    socket.on("greetings", message => {
        console.log(message)
    })
</script>

Öffne die Entwickler Konsole deines Browsers (z.B. mit Ctrl+Shift+I)

In adaptor:ex, erstelle eine neue Session von deinem Level und löse den State mit der Send Socket Message action aus.

Wenn die Verbindung zwischen adaptor:ex und Webseite funktioniert siehts du in der Entwickeler Konsole die Nachricht, die du über die Send Socket Message action gesendet hast.

Eine Nachricht von der Webseite empfangen

Füge deiner Seite ein Interaktionslement, etwa einen Button, hinzu um Daten an den adaptor:ex Server zu senden.

<body>
    <button onclick="sendGo()">GO</button> 
</body>

Und verknüpfe den Button mit der socket.emit Funktion.

<script>
    const socket = io("http://localhost:8081/Tutorial/socketio/my_app")

    function sendGo() {
        socket.emit("button", "go", (response) => {
            console.log(response)
        })
    }
</script>

Füge deinem Level in adaptor:ex eine On Socket Message action hinzu, in der du auf Nachrichten auf dem topic button reagierst.

On Socket.IO Message

{
    "namespace": "MyAPP",
    "topic": "button",
    "if": [
        {
        "equals": [
            "go"
        ],
        "respond": "it's on",
        "next": "Go"
        }
    ]
}

State name ist WaitForGo Namespace MyAPP topic ist button, equals ist go, respond ist it's on und next state ist Go

Erstelle einen neuen State Go, der ausgelöst werden soll, wenn der Button geklickt wird. Löst du nun den State mit der On Socket Message action aus und klickst auf der Webseite auf den "GO" Button, sollte deine Session in den Go State wechseln.

WaitForGo wird ausgelöst. Anschließend wird der GO Button im Browser geklickt

Einen room erstellen

Füge zwei neue Buttons zur Seite hinzu

<body>
    <button onclick="createRoom()">CREATE</button> 
    <button onclick="joinRoom()">JOIN</button> 
    <button onclick="sendGo()">GO</button> 
</body>

Und verknüpfe die Buttons mit der socket.emit Funktion und den topics create und join.

<script>
    const socket = io("http://localhost:8081/Tutorial/socketio/my_app")

    function createRoom() {
        socket.emit("create", "myroom", (response) => {
            console.log(response)
        })
    }

    function joinRoom() {
        socket.emit("join", "myroom", (response) => {
            console.log(response)
        })
    }
</script>

Klicks du auf create, wird in adaptor:ex ein neuer socket.io room erstellt.

Ergänze den room nun in adaptor:ex in der Send Socket.IO Message und der On Socket Message action.

Öffnest du deine Seite in einem weiteren Browser Fenster oder Tab, werden Nachrichten dann nur mit den Seiten ausgetauscht, die dem room übder den JOIN button beigetreten sind.

Rooms zur Spiel, Player und Session Verwaltung einsetzen

Die socket.io rooms bieten sich an um unterschiedliche Verläufe von getrennten Spielen oder von Spielern in einer gemeinsamen Spielrunde zu verwalten. Mit dem Socket.IO Plugin kannst du automatisch room IDs erstellen lassen, die mit einer Session deiner adaptor:ex Level verknüpft sind. Nutzer deiner Webseite können so etwa neue Spielrunden erstellen oder einem bestehenden Spiel beitreten.

Öffne die Einstellungen deines Namespace in den Socket.IO Plugin settings unter Game -> Settings.

Game Menü Settings, Socket.IO Plugin

Füge im Namespace über das Settings Menü die Optionen level, level argument und room id pattern hinzu.

Häkchen bei den 3 genannten Optionen

Gib in der level Option, den Namen deines neu erstelltes Level an (hier socketio).

Wir können die bereits existierende players collection nutzen um room Informationen zu speichern. Gib als level argument name einen Namen an unter dem du die room infos adressieren kannst (hier Player). Als type die collection in der neue room items angelegt werden sollen (hier players).

Optional kannst du mit room id pattern noch das Format der automatisch generierten room Namen anpassen (hier length: 5 und characters: 0123456789).

Socketio Namespace level Einstellungen

Klicke Save um die Einstellungen zu übernehmen.

In deinem Level, passe die room options in den Send Socket.IO Message und On Socket Message an. Verwende den Wert, den du als level argument name angegeben hast (hier Player) als variable.

Send Socket.IO Message

{
    "namespace": "MyAPP",
    "room": "[[Player]]",
    "topic": "greetings",
    "message": "Nice to meet you!"
}

room mit [[Player]] ersetzt

Note

Die room id ist im jeweils neu erstellten players Item unter socketio.id gespeichert. Verwendest du wie hier ein Data Item in der room Option, nutzt die Send Socket.IO Message action die darin gespeicherte id. [[Player]] ist also ein synonym für [[Player.socketio.id]].

Verbinde deine actions über eine Next oder Timeout action mit dem START State und miteinander.

Eine timeout action zu START and HelloWeb hinzugefügt

Entferne jetzt den room name in der createRoom Funktion auf deiner Webseite. So wird dann bei Klick stattdessen ein Name automatisch generiert.

Die neu generierte room id wird in response zurückgegeben. Sie kann anschließend genutzt werden um sich in Zukunft mit der selben Session zu verbinden.

Erstelle dafür noch ein Ausgabe- und ein Eingabefeld auf deiner Webseite, z.B.:

<body>
    <button onclick="createRoom()">CREATE</button>
    <span id="new-room"></span><br>
    <input id="room" type="text" placeholder="Enter room">
    <button onclick="joinRoom()">JOIN</button><br>
    <button onclick="sendGo()">GO</button>
</body>
function createRoom() {
    socket.emit("create", "", (response) => {
        console.log(response)
        document.getElementById("new-room").innerText = response.id
    })
}

function joinRoom() {
    const room = document.getElementById("room").value
    socket.emit("join", room, (response) => {
        console.log(response)
    })
}

Wechsle in deinem Level in den Live Modus und lösche alle bestehenden Sessions . Klickst du nun auf den CREATE button auf deiner Webseite, wird eine neue Session erstellt. Im HelloWeb State wird dann eine Nachricht an den client gesendet. Sobald der WaitForGo State ausgelöst wurde, wartet die Session darauf, dass der Go Button gedrückt wird.

Klick auf CREATE später auf GO

Da create automatisch ein join durchführt und dem neu erstellten room beitritt brauchst du an dieser Stelle nicht explizit join zu nutzen. Ab jetzt kannst du aber nach einem page reload oder in einem anderen Browser fenster oder tab dem neu erstellten room und damit der Session deines Levels mit der angegebenen id beitreten.

Klick auf JOIN später auf GO

Werden nun weitere rooms erstellt ist so sichergestellt, das jedes Spiel oder jeder Player einen unabhängigen Session verlauf startet.

Mit jedem room wird in diesem Setup ein eigenes Data Item in der players collection erstellt. Über das Level Argument (hier Player) kannst du so auch Daten die für den individuellen Spielverlauf wichtig sind, z.B. mit der Set Variable action speichern.