Cliente Godot para servidor Nakama escrito em GDScript.
Nakama é um servidor de código aberto projetado para alimentar jogos e aplicativos modernos. Os recursos incluem contas de usuário, bate-papo, redes sociais, matchmaker, multijogador em tempo real e muito mais.
Este cliente implementa todas as opções de API e soquete com o servidor. Está escrito em GDScript para suportar Godot Engine 4.0+
.
A documentação completa está online - https://heroiclabs.com/docs
Atualmente você está vendo a versão Godot 4 do cliente Nakama para Godot.
Se você estiver usando Godot 3, precisará usar o branch 'godot-3' no GitHub.
Você precisará configurar o servidor e o banco de dados antes de se conectar ao cliente. A maneira mais simples é usar o Docker, mas dê uma olhada na documentação do servidor para outras opções.
Instale e execute os servidores. Siga estas instruções.
Baixe o cliente na página de lançamentos e importe-o para o seu projeto. Você também pode baixá-lo do repositório de ativos.
Adicione o singleton Nakama.gd
(em addons/com.heroiclabs.nakama/
) como um carregamento automático no Godot.
Use as credenciais de conexão para construir um objeto cliente usando o singleton.
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 )
O objeto cliente possui muitos métodos para executar vários recursos no servidor ou abrir conexões de soquete em tempo real com o servidor.
Existem várias maneiras de autenticar no servidor. A autenticação pode criar um usuário se ele ainda não existir com essas credenciais. Também é fácil autenticar com um perfil social do Google Play Games, Facebook, Game Center, etc.
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 )
Quando autenticado, o servidor responde com um token de autenticação (JWT) que contém propriedades úteis e é desserializado em um objeto NakamaSession
.
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 )
Recomenda-se armazenar o token de autenticação da sessão e verificar na inicialização se ele expirou. Se o token expirou, você deverá autenticar novamente. O tempo de expiração do token pode ser alterado conforme configuração no servidor.
var authtoken = "restored from somewhere"
var session2 = NakamaClient . restore_session ( authtoken )
if session2 . expired :
print ( "Session has expired. Must reauthenticate!" )
NOTA: A duração da vida útil de uma sessão pode ser alterada no servidor com o argumento do sinalizador de comando --session.token_expiry_sec
.
O cliente inclui muitas APIs integradas para vários recursos do servidor de jogo. Eles podem ser acessados com os métodos assíncronos. Ele também pode chamar lógica personalizada em funções RPC no servidor. Eles também podem ser executados com um objeto soquete.
Todas as solicitações são enviadas com um objeto de sessão que autoriza o cliente.
var account = await client . get_account_async ( session )
print ( account . user . id )
print ( account . user . username )
print ( account . wallet )
Como Godot Engine não suporta exceções, sempre que você fizer uma solicitação assíncrona via cliente ou soquete, você pode verificar se ocorreu algum erro através do método is_exception()
.
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" )
O cliente pode criar um ou mais soquetes com o servidor. Cada soquete pode ter seus próprios ouvintes de eventos registrados para respostas recebidas do servidor.
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 fornece uma API multijogador de alto nível, permitindo que os desenvolvedores criem RPCs, chamando funções que são executadas em outros pares em uma partida multijogador.
Por exemplo:
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 fornece vários back-ends integrados para envio de RPCs, incluindo: ENet, WebSockets e WebRTC.
No entanto, você também pode usar o cliente Nakama como backend! Isso pode permitir que você continue usando a familiar API multijogador de alto nível de Godot, mas com os RPCs enviados de forma transparente em uma partida de Nakama em tempo real.
Para fazer isso, você precisa usar a classe NakamaMultiplayerBridge
:
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 )
Você também pode se conectar a qualquer um dos sinais usuais no MultiplayerAPI
, por exemplo:
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 )
Então você precisa entrar em uma partida, usando um dos seguintes métodos:
Crie uma nova partida privada, com seu cliente como anfitrião.
multiplayer_bridge . create_match ()
Participe de uma partida privada.
multiplayer_bridge . join_match ( match_id )
Crie ou participe de uma partida privada com o nome fornecido.
multiplayer_bridge . join_named_match ( match_name )
Use o matchmaker para encontrar e participar de uma partida pública.
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 )
Depois que o sinal "match_joined" for emitido, você pode começar a enviar RPCs normalmente com a função rpc()
e chamar quaisquer outras funções associadas à API Multiplayer de alto nível, como get_tree().get_multiplayer().get_unique_id()
e node.set_network_authority(peer_id)
e node.is_network_authority()
.
Se estiver usando a versão .NET do Godot com suporte C#, você pode usar o cliente Nakama .NET, que pode ser instalado via NuGet:
dotnet add package NakamaClient
Este complemento inclui algumas classes C# para uso com o cliente .NET, para fornecer integração mais profunda com Godot:
GodotLogger
: Um registrador que imprime no console Godot.GodotHttpAdapter
: Um adaptador HTTP que usa o nó HTTPRequest de Godot.GodotWebSocketAdapter
: Um adaptador de soquete que usa o WebSocketClient de Godot.Aqui está um exemplo de como usá-los:
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 ) ;
Nota: O cliente Nakama .NET pronto para uso funcionará bem com compilações de desktop do seu jogo! No entanto, não funcionará com compilações HTML5, a menos que você use as classes GodotHttpAdapter
e GodotWebSocketAdapter
.
Satori é um servidor liveops para jogos que possibilita análises acionáveis, testes A/B e configuração remota. Use o cliente Satori Godot para se comunicar com Satori de dentro do seu jogo Godot.
Satori só é compatível com Godot 4.
A documentação completa está online - https://heroiclabs.com/docs/satori/client-libraries/godot/index.html
Adicione o singleton Satori.gd
(em addons/com.heroiclabs.nakama/
) como um carregamento automático no Godot.
Crie um objeto cliente que aceite a chave de API que você recebeu como cliente Satori.
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 )
Em seguida, autentique-se no servidor para obter sua sessão.
// 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." )
Usando o cliente, você pode obter quaisquer experimentos ou sinalizadores de recurso aos quais o usuário pertence.
var experiments = await _client . get_experiments_async ( session , [ "experiment1" , "Experiment2" ])
var flag = await _client . get_flag_async ( session , "FlagName" )
Você também pode enviar eventos arbitrários ao servidor:
var _event = Event . new ( "gameFinished" , Time . get_unix_time_from_system ())
await _client . event_async ( session , _event )
O roteiro de desenvolvimento é gerenciado à medida que problemas do GitHub e solicitações pull são bem-vindas. Se você estiver interessado em melhorar o código, abra um problema para discutir as mudanças ou entre e discuta no fórum da comunidade.
Para executar testes você precisará executar o servidor e o banco de dados. A maioria dos testes são escritos como testes de integração executados no servidor. Uma abordagem rápida que usamos com nosso fluxo de trabalho de teste é usar o arquivo de composição do Docker descrito na documentação.
Além disso, você precisará copiar (ou vincular simbolicamente) a pasta addons
dentro da pasta test_suite
. Agora você pode executar o projeto test_suite
no Godot Editor.
Para executar os testes em uma máquina headless (sem GPU), você pode baixar uma cópia do Godot Headless e executá-la na linha de comando.
Para automatizar este procedimento, mova o binário headless para test_suite/bin/godot.elf
e execute os testes por meio do script de shell test_suite/run_tests.sh
(o código de saída reportará falha/sucesso no teste).
cd nakama
docker-compose -f ./docker-compose-postgres.yml up
cd ..
cd nakama-godot
sh test_suite/run_tests.sh
Para preparar uma nova versão para distribuição, basta compactar a pasta addons recursivamente (possivelmente adicionando CHANGELOG
, LICENSE
e README.md
também).
Em sistemas Unix, você pode executar o seguinte comando (substituindo $VERSION
pelo número da versão desejada). Lembre-se de atualizar o arquivo CHANGELOG
primeiro.
zip -r nakama- $VERSION .zip addons/ LICENSE CHANGELOG.md README.md
Este projeto está licenciado sob a licença Apache-2.