Godot-Client für Nakama-Server, geschrieben in GDScript.
Nakama ist ein Open-Source-Server, der für den Betrieb moderner Spiele und Apps entwickelt wurde. Zu den Funktionen gehören Benutzerkonten, Chat, soziale Netzwerke, Matchmaker, Echtzeit-Multiplayer und vieles mehr.
Dieser Client implementiert die vollständigen API- und Socket-Optionen mit dem Server. Es ist in GDScript geschrieben, um Godot Engine 4.0+
zu unterstützen.
Die vollständige Dokumentation ist online – https://heroiclabs.com/docs
Sie sehen sich derzeit die Godot 4-Version des Nakama-Clients für Godot an.
Wenn Sie Godot 3 verwenden, müssen Sie den Zweig „godot-3“ auf GitHub verwenden.
Sie müssen den Server und die Datenbank einrichten, bevor Sie eine Verbindung mit dem Client herstellen können. Der einfachste Weg ist die Verwendung von Docker. Weitere Optionen finden Sie in der Serverdokumentation.
Installieren Sie die Server und führen Sie sie aus. Befolgen Sie diese Anweisungen.
Laden Sie den Client von der Release-Seite herunter und importieren Sie ihn in Ihr Projekt. Sie können es auch aus dem Asset-Repository herunterladen.
Fügen Sie den Nakama.gd
-Singleton (in addons/com.heroiclabs.nakama/
) als Autoload in Godot hinzu.
Verwenden Sie die Verbindungsanmeldeinformationen, um mithilfe des Singletons ein Clientobjekt zu erstellen.
extends Node
func _ready ():
var scheme = "http"
var host = "127.0.0.1"
var port = 7350
var server_key = "defaultkey"
var client := Nakama . create_client ( server_key , host , port , scheme )
Das Client-Objekt verfügt über viele Methoden, um verschiedene Funktionen im Server auszuführen oder Echtzeit-Socket-Verbindungen mit dem Server zu öffnen.
Es gibt verschiedene Möglichkeiten, sich beim Server zu authentifizieren. Durch die Authentifizierung kann ein Benutzer erstellt werden, wenn dieser noch nicht mit diesen Anmeldeinformationen vorhanden ist. Es ist auch einfach, sich mit einem sozialen Profil von Google Play Games, Facebook, Game Center usw. zu authentifizieren.
var email = "[email protected]"
var password = "batsignal"
# Use 'await' to wait for the request to complete.
var session : NakamaSession = await client . authenticate_email_async ( email , password )
print ( session )
Bei der Authentifizierung antwortet der Server mit einem Authentifizierungstoken (JWT), der nützliche Eigenschaften enthält und in ein NakamaSession
Objekt deserialisiert wird.
print ( session . token ) # raw JWT token
print ( session . user_id )
print ( session . username )
print ( "Session has expired: %s " % session . expired )
print ( "Session expires at: %s " % session . expire_time )
Es wird empfohlen, das Authentifizierungstoken der Sitzung zu speichern und beim Start zu prüfen, ob es abgelaufen ist. Wenn das Token abgelaufen ist, müssen Sie sich erneut authentifizieren. Die Ablaufzeit des Tokens kann als Einstellung im Server geändert werden.
var authtoken = "restored from somewhere"
var session2 = NakamaClient . restore_session ( authtoken )
if session2 . expired :
print ( "Session has expired. Must reauthenticate!" )
HINWEIS: Die Länge der Lebensdauer einer Sitzung kann auf dem Server mit dem Befehlsflag-Argument --session.token_expiry_sec
geändert werden.
Der Client enthält zahlreiche integrierte APIs für verschiedene Funktionen des Spieleservers. Auf diese kann mit den asynchronen Methoden zugegriffen werden. Es kann auch benutzerdefinierte Logik in RPC-Funktionen auf dem Server aufrufen. Diese können auch mit einem Socket-Objekt ausgeführt werden.
Alle Anfragen werden mit einem Sitzungsobjekt gesendet, das den Client autorisiert.
var account = await client . get_account_async ( session )
print ( account . user . id )
print ( account . user . username )
print ( account . wallet )
Da Godot Engine keine Ausnahmen unterstützt, können Sie jedes Mal, wenn Sie eine asynchrone Anfrage über den Client oder Socket stellen, mit der Methode is_exception()
überprüfen, ob ein Fehler aufgetreten ist.
var an_invalid_session = NakamaSession . new () # An empty session, which will cause and error when we use it.
var account2 = await client . get_account_async ( an_invalid_session )
print ( account2 ) # This will print the exception
if account2 . is_exception ():
print ( "We got an exception" )
Der Client kann einen oder mehrere Sockets mit dem Server erstellen. Für jeden Socket können eigene Ereignis-Listener für vom Server empfangene Antworten registriert werden.
var socket = Nakama . create_socket_from ( client )
socket . connected . connect ( self . _on_socket_connected )
socket . closed . connect ( self . _on_socket_closed )
socket . received_error . connect ( self . _on_socket_error )
await socket . connect_async ( session )
print ( "Done" )
func _on_socket_connected ():
print ( "Socket connected." )
func _on_socket_closed ():
print ( "Socket closed." )
func _on_socket_error ( err ):
printerr ( "Socket error %s " % err )
Godot bietet eine High-Level-Multiplayer-API, die es Entwicklern ermöglicht, RPCs zu erstellen und Funktionen aufzurufen, die auf anderen Peers in einem Multiplayer-Match ausgeführt werden.
Zum Beispiel:
func _process ( delta ):
if not is_multiplayer_authority ():
return
var input_vector = get_input_vector ()
# Move the player locally.
velocity = input_vector * SPEED
move_and_slide ()
# Then update the player's position on all other connected clients.
update_remote_position . rpc ( position )
@rpc ( any_peer )
func update_remote_position ( new_position ):
position = new_position
Godot bietet eine Reihe integrierter Backends zum Senden der RPCs, darunter ENet, WebSockets und WebRTC.
Sie können den Nakama-Client jedoch auch als Backend verwenden! Auf diese Weise können Sie weiterhin Godots bekannte High-Level-Multiplayer-API verwenden, wobei die RPCs jedoch transparent über ein Echtzeit-Nakama-Match gesendet werden.
Dazu müssen Sie die Klasse NakamaMultiplayerBridge
verwenden:
var multiplayer_bridge
func _ready ():
# [...]
# You must have a working 'socket', created as described above.
multiplayer_bridge = NakamaMultiplayerBridge . new ( socket )
multiplayer_bridge . match_join_error . connect ( self . _on_match_join_error )
multiplayer_bridge . match_joined . connect ( self . _on_match_joined )
get_tree (). get_multiplayer (). set_multiplayer_peer ( multiplayer_bridge . multiplayer_peer )
func _on_match_join_error ( error ):
print ( "Unable to join match: " , error . message )
func _on_match_join () -> void :
print ( "Joined match with id: " , multiplayer_bridge . match_id )
Sie können sich auch mit jedem der üblichen Signale auf MultiplayerAPI
verbinden, zum Beispiel:
get_tree (). get_multiplayer (). peer_connected . connect ( self . _on_peer_connected )
get_tree (). get_multiplayer (). peer_disconnected . connect ( self . _on_peer_disconnected )
func _on_peer_connected ( peer_id ):
print ( "Peer joined match: " , peer_id )
func _on_peer_disconnected ( peer_id ):
print ( "Peer left match: " , peer_id )
Dann müssen Sie einem Match beitreten, indem Sie eine der folgenden Methoden verwenden:
Erstellen Sie ein neues privates Match mit Ihrem Kunden als Gastgeber.
multiplayer_bridge . create_match ()
Nehmen Sie an einem privaten Match teil.
multiplayer_bridge . join_match ( match_id )
Erstellen Sie ein privates Match mit dem angegebenen Namen oder nehmen Sie daran teil.
multiplayer_bridge . join_named_match ( match_name )
Verwenden Sie den Matchmaker, um ein öffentliches Match zu finden und daran teilzunehmen.
var ticket = await socket . add_matchmaker_async ()
if ticket . is_exception ():
print ( "Error joining matchmaking pool: " , ticket . get_exception (). message )
return
multiplayer_bridge . start_matchmaking ( ticket )
Nachdem das Signal „match_joined“ ausgegeben wurde, können Sie wie gewohnt mit dem Senden von RPCs mit der Funktion rpc()
beginnen und alle anderen Funktionen aufrufen, die mit der High-Level-Multiplayer-API verknüpft sind, wie z. B. get_tree().get_multiplayer().get_unique_id()
und node.set_network_authority(peer_id)
und node.is_network_authority()
.
Wenn Sie die .NET-Version von Godot mit C#-Unterstützung verwenden, können Sie den Nakama .NET-Client verwenden, der über NuGet installiert werden kann:
dotnet add package NakamaClient
Dieses Add-on enthält einige C#-Klassen zur Verwendung mit dem .NET-Client, um eine tiefere Integration mit Godot zu ermöglichen:
GodotLogger
: Ein Logger, der auf der Godot-Konsole druckt.GodotHttpAdapter
: Ein HTTP-Adapter, der den HTTPRequest-Knoten von Godot verwendet.GodotWebSocketAdapter
: Ein Socket-Adapter, der Godots WebSocketClient verwendet.Hier ist ein Beispiel für deren Verwendung:
var http_adapter = new GodotHttpAdapter ( ) ;
// It's a Node, so it needs to be added to the scene tree.
// Consider putting this in an autoload singleton so it won't go away unexpectedly.
AddChild ( http_adapter ) ;
const string scheme = "http" ;
const string host = "127.0.0.1" ;
const int port = 7350 ;
const string serverKey = "defaultkey" ;
// Pass in the 'http_adapter' as the last argument.
var client = new Client ( scheme , host , port , serverKey , http_adapter ) ;
// To log DEBUG messages to the Godot console.
client . Logger = new GodotLogger ( "Nakama" , GodotLogger . LogLevel . DEBUG ) ;
ISession session ;
try {
session = await client . AuthenticateDeviceAsync ( OS . GetUniqueId ( ) , "TestUser" , true ) ;
}
catch ( ApiResponseException e ) {
GD . PrintErr ( e . ToString ( ) ) ;
return ;
}
var websocket_adapter = new GodotWebSocketAdapter ( ) ;
// Like the HTTP adapter, it's a Node, so it needs to be added to the scene tree.
// Consider putting this in an autoload singleton so it won't go away unexpectedly.
AddChild ( websocket_adapter ) ;
// Pass in the 'websocket_adapter' as the last argument.
var socket = Socket . From ( client , websocket_adapter ) ;
Hinweis: Der sofort einsatzbereite Nakama .NET-Client funktioniert problemlos mit Desktop-Builds Ihres Spiels! Es funktioniert jedoch nicht mit HTML5-Builds, es sei denn, Sie verwenden die Klassen GodotHttpAdapter
und GodotWebSocketAdapter
.
Satori ist ein Live-Ops-Server für Spiele, der umsetzbare Analysen, A/B-Tests und Remote-Konfiguration ermöglicht. Verwenden Sie den Satori Godot Client, um innerhalb Ihres Godot-Spiels mit Satori zu kommunizieren.
Satori ist nur mit Godot 4 kompatibel.
Die vollständige Dokumentation ist online – https://heroiclabs.com/docs/satori/client-libraries/godot/index.html
Fügen Sie den Singleton Satori.gd
(in addons/com.heroiclabs.nakama/
) als Autoload in Godot hinzu.
Erstellen Sie ein Client-Objekt, das den API-Schlüssel akzeptiert, den Sie als Satori-Kunde erhalten haben.
extends Node
func ready ():
var scheme = "http"
var host = "127.0.0.1"
var port : Int = 7450
var apiKey = "apiKey"
var client := Satori . create_client ( apiKey , host , port , scheme )
Authentifizieren Sie sich dann beim Server, um Ihre Sitzung zu erhalten.
// Authenticate with the Satori server .
var session = await _client . authenticate_async ( "your-id" )
if session . is_exception ():
print ( "Error authenticating: " + session . get_exception (). _message )
else :
print ( "Authenticated successfully." )
Mit dem Client können Sie alle Experimente oder Feature-Flags abrufen, zu denen der Benutzer gehört.
var experiments = await _client . get_experiments_async ( session , [ "experiment1" , "Experiment2" ])
var flag = await _client . get_flag_async ( session , "FlagName" )
Sie können auch beliebige Ereignisse an den Server senden:
var _event = Event . new ( "gameFinished" , Time . get_unix_time_from_system ())
await _client . event_async ( session , _event )
Die Entwicklungs-Roadmap wird verwaltet, da GitHub-Probleme und Pull-Requests willkommen sind. Wenn Sie daran interessiert sind, den Code zu verbessern, öffnen Sie bitte ein Problem, um die Änderungen zu besprechen, oder kommen Sie vorbei und diskutieren Sie es im Community-Forum.
Um Tests auszuführen, müssen Sie den Server und die Datenbank ausführen. Die meisten Tests werden als Integrationstests geschrieben, die auf dem Server ausgeführt werden. Ein schneller Ansatz, den wir für unseren Testworkflow verwenden, ist die Verwendung der in der Dokumentation beschriebenen Docker-Compose-Datei.
Darüber hinaus müssen Sie den Ordner addons
im Ordner test_suite
kopieren (oder mit einem Symlink versehen). Sie können das test_suite
Projekt jetzt über den Godot-Editor ausführen.
Um die Tests auf einem Headless-Computer (ohne GPU) auszuführen, können Sie eine Kopie von Godot Headless herunterladen und über die Befehlszeile ausführen.
Um diesen Vorgang zu automatisieren, verschieben Sie die Headless-Binärdatei nach test_suite/bin/godot.elf
und führen Sie die Tests über das Shell-Skript test_suite/run_tests.sh
aus (der Exit-Code meldet Testfehler/-erfolg).
cd nakama
docker-compose -f ./docker-compose-postgres.yml up
cd ..
cd nakama-godot
sh test_suite/run_tests.sh
Um eine neue Version für die Verteilung vorzubereiten, komprimieren Sie einfach den Add-Ons-Ordner rekursiv (und fügen Sie möglicherweise auch CHANGELOG
, LICENSE
und README.md
hinzu).
Auf Unix-Systemen können Sie den folgenden Befehl ausführen (wobei $VERSION
durch die gewünschte Versionsnummer ersetzt wird). Denken Sie daran, zuerst die CHANGELOG
Datei zu aktualisieren.
zip -r nakama- $VERSION .zip addons/ LICENSE CHANGELOG.md README.md
Dieses Projekt ist unter der Apache-2-Lizenz lizenziert.