-
Notifications
You must be signed in to change notification settings - Fork 1
Client Server Kommunikation
UserApps bestehen aus einem Server-Teil (JavaScript auf dem AppServer) und einem Client-Teil (HTML/JS im Knuddels-Client). Dieses Kapitel erklärt, wie die beiden miteinander kommunizieren.
┌─────────────────────┐ ┌─────────────────────┐
│ Client (Browser) │ Events │ Server (Rhino) │
│ │ ──────► │ │
│ www/index.html │ │ main.js │
│ Client.sendEvent() │ │ this.onEventReceived│
│ │ ◄────── │ │
│ Client.addEventListener() │ session.sendEvent()│
└─────────────────────┘ └─────────────────────┘
Bevor Client-Server-Kommunikation stattfinden kann, musst du dem Nutzer ein HTML-UI anzeigen. Das geschieht über AppContent:
// Servercode (innerhalb von var App = (new function() { ... }());)
this.chatCommands = {
openApp: function(user, params, func) {
// pageData: initiale Daten, die an den Client geschickt werden
var pageData = {
username: user.getNick(),
points: user.getPersistence().getNumber('points', 0)
};
var htmlFile = new HTMLFile("index.html", pageData);
var popup = AppContent.popupContent(htmlFile, 480, 720);
popup.setResponsive(true);
if (user.canShowAppViewMode(AppViewMode.Popup)) {
user.sendAppContent(popup);
} else {
user.sendPrivateMessage("Die App kann auf deinem Gerät leider nicht angezeigt werden.");
}
}
};Wenn der Server AppContent an einen Nutzer sendet, wird das HTML nicht isoliert dargestellt, sondern in der Knuddels-Client-Umgebung. Diese stellt automatisch das globale Client-Objekt bereit, über das die Kommunikation mit dem Server läuft.
Die beim Erstellen der HTMLFile übergebenen Daten sind im Client verfügbar:
// Clientcode (www/index.html)
var pageData = {};
if (typeof Client !== 'undefined') {
pageData = Client.pageData;
}
// pageData enthält jetzt { username: "...", points: 42 }
document.getElementById('name').textContent = pageData.username;Hinweis:
pageDatakann nur serialisierbare Daten enthalten (Strings, Zahlen, Arrays, Objekte). Keine Funktionen!
Der Client sendet Events an den Server mit Client.sendEvent():
// Clientcode
function kaufeItem(itemId) {
if (typeof Client !== 'undefined' && Client.sendEvent) {
Client.sendEvent('kaufeItem', { itemId: itemId, menge: 1 });
}
}Der Server empfängt das Event im onEventReceived-Hook:
// Servercode (innerhalb von var App = (new function() { ... }());)
this.onEventReceived = function(user, type, data, appContentSession) {
if (type === "kaufeItem") {
var itemId = data.itemId;
var menge = data.menge;
// Kauf verarbeiten...
KnuddelsServer.getDefaultLogger().info(
user.getNick() + ' kauft Item ' + itemId
);
// Antwort an den Client senden
appContentSession.sendEvent('kaufErfolgreich', {
itemId: itemId,
neuerKontostand: 950
});
}
};Der Server sendet Events an den Client über die appContentSession:
// Servercode (innerhalb von var App = (new function() { ... }());)
this.onEventReceived = function(user, type, data, appContentSession) {
if (type === "getHighscore") {
var highscore = berechneHighscore();
appContentSession.sendEvent('highscore', { daten: highscore });
}
};Der Client lauscht auf Events mit Client.addEventListener():
// Clientcode
if (typeof Client !== 'undefined') {
Client.addEventListener("highscore", function(event) {
var daten = event.data;
zeigeHighscore(daten);
});
Client.addEventListener("kaufErfolgreich", function(event) {
document.getElementById('kontostand').textContent = event.data.neuerKontostand;
});
}Du kannst dein Frontend auch ohne Server lokal im Browser testen, indem du prüfst, ob Client definiert ist:
// Clientcode
var pageData = {};
if (typeof Client !== 'undefined') {
// Läuft im Knuddels-Client
pageData = Client.pageData;
} else {
// Läuft lokal im Browser – Testdaten verwenden
pageData = {
username: "TestUser",
points: 100
};
}Du kannst reagieren, wenn ein Nutzer das App-Fenster schließt:
// Servercode (innerhalb von var App = (new function() { ... }());)
this.chatCommands = {
openApp: function(user, params, func) {
var htmlFile = new HTMLFile("index.html", {});
var popup = AppContent.popupContent(htmlFile, 480, 720);
user.sendAppContent(popup);
popup.addCloseListener(function(user, appContent) {
user.sendPrivateMessage(
"App geschlossen. Klicke °>/openApp|hier<°, um sie erneut zu öffnen."
);
});
}
};- sendEvent-Daten: maximal 10.000 Zeichen pro Event
- Frequenz: Das Versenden von sehr vielen Events in kurzer Zeit kann vom Server gedrosselt werden. Achte auf Datensparsamkeit.
- pageData: Sollte möglichst kompakt sein, da es bei jedem Öffnen übertragen wird
Standardmäßig laufen Events über den Knuddels-Chat-Protokoll-Kanal. Für mehr Geschwindigkeit kannst du Direct Connection aktivieren:
# In app.config
directConnection = knuddelsDE
# Für den Dev-Server:
# directConnection = knuddelsDEVVorteile: Schnellere Datenübertragung, größere Datenmengen möglich
Nachteile: Manche Nutzer haben Probleme damit (App schließt sich, öffnet sich nicht). Verwende Direct Connection nur, wenn niedrige Latenz oder große Datenmengen wirklich nötig sind.
- Client – Das Client-Objekt im Frontend
- Client.Event – Event-Objekt
- AppContent – UI-Container
- AppContentSession – Aktive UI-Session
- Erste Schritte – Voraussetzungen, Einrichtung, deine erste App
-
Projektstruktur – Dateien, Ordner und
app.config - Dev-Server – Entwicklungsumgebung und Testen
-
App-Lifecycle und Hooks –
onAppStart,onUserJoinedund Co. -
Server-API Grundlagen –
KnuddelsServer,Channel,Logger - Client-Server-Kommunikation – Events zwischen Frontend und Backend
-
Benutzer und Nachrichten –
User,BotUser, Nachrichten senden - HTML-UI und AppContent – Popups, Overlays, Globale Apps-UI
-
Datenspeicherung –
AppPersistence,UserPersistence -
Knuddel und Zahlungen – Transfers, Käufe,
KnuddelAccount - Toplisten – Ranglisten und Highscores
- Globale Apps – Apps im "Apps & Spiele"-Menü
- Quests – Aufgaben für Nutzer
- Externe Server-Kommunikation – HTTP-Requests an externe APIs
- Tutorials – Übersicht aller Tutorials
- Tic-Tac-Toe – Multiplayer-Spiel mit Bestenliste
- Best Practices – Tipps, Limits und häufige Fehler
- FAQ – Häufig gestellte Fragen
- KCode-Formatierung – Nachrichten-Formatierung mit KCode