用 GDScript 编写的 Nakama 服务器的 Godot 客户端。
Nakama 是一款开源服务器,旨在为现代游戏和应用程序提供支持。功能包括用户帐户、聊天、社交、媒人、实时多人游戏等等。
该客户端通过服务器实现完整的 API 和套接字选项。它是用 GDScript 编写的,支持 Godot Engine 4.0+
。
完整文档在线 - https://heroiclabs.com/docs
您当前正在查看 Godot 的 Nakama 客户端的 Godot 4 版本。
如果您使用 Godot 3,则需要使用 GitHub 上的“godot-3”分支。
您需要先设置服务器和数据库,然后才能连接客户端。最简单的方法是使用 Docker,但请查看服务器文档以了解其他选项。
安装并运行服务器。请遵循这些说明。
从发布页面下载客户端并将其导入到您的项目中。您还可以从资产存储库下载它。
添加Nakama.gd
单例(在addons/com.heroiclabs.nakama/
中)作为 Godot 中的自动加载。
使用连接凭据通过单例构建客户端对象。
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 )
客户端对象有许多方法来执行服务器中的各种功能或打开与服务器的实时套接字连接。
有多种方法可以对服务器进行身份验证。如果用户尚不存在且具有这些凭据,则身份验证可以创建用户。使用来自 Google Play Games、Facebook、Game Center 等的社交资料进行身份验证也很容易。
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 )
经过身份验证后,服务器会使用身份验证令牌 (JWT) 进行响应,其中包含有用的属性并反序列化为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 )
建议存储会话中的身份验证令牌,并在启动时检查它是否已过期。如果令牌已过期,您必须重新进行身份验证。令牌的到期时间可以作为服务器中的设置进行更改。
var authtoken = "restored from somewhere"
var session2 = NakamaClient . restore_session ( authtoken )
if session2 . expired :
print ( "Session has expired. Must reauthenticate!" )
注意:可以使用--session.token_expiry_sec
命令标志参数在服务器上更改会话生命周期的长度。
客户端包含许多用于游戏服务器各种功能的内置 API。可以使用异步方法访问这些。它还可以调用服务器上 RPC 函数中的自定义逻辑。这些也可以使用套接字对象来执行。
所有请求都通过授权客户端的会话对象发送。
var account = await client . get_account_async ( session )
print ( account . user . id )
print ( account . user . username )
print ( account . wallet )
由于 Godot 引擎不支持异常,因此每当您通过客户端或套接字发出异步请求时,您都可以通过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" )
客户端可以与服务器创建一个或多个套接字。每个套接字都可以注册自己的事件侦听器,以接收从服务器接收的响应。
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 提供了高级多人游戏 API,允许开发人员制作 RPC,在多人游戏比赛中调用在其他对等点上运行的函数。
例如:
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 提供了许多用于发送 RPC 的内置后端,包括:ENet、WebSockets 和 WebRTC。
但是,您也可以使用 Nakama 客户端作为后端!这可以让您继续使用 Godot 熟悉的高级多人游戏 API,但通过实时 Nakama 比赛透明地发送 RPC。
为此,您需要使用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 )
您还可以连接到MultiplayerAPI
上的任何常用信号,例如:
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 )
然后您需要使用以下方法之一加入比赛:
创建一场新的私人比赛,由您的客户作为主持人。
multiplayer_bridge . create_match ()
参加私人比赛。
multiplayer_bridge . join_match ( match_id )
使用给定名称创建或加入私人比赛。
multiplayer_bridge . join_named_match ( match_name )
使用媒人查找并加入公开比赛。
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 )
发出“match_joined”信号后,您可以像往常一样开始使用rpc()
函数发送 RPC,并调用与高级多人游戏 API 关联的任何其他函数,例如get_tree().get_multiplayer().get_unique_id()
和node.set_network_authority(peer_id)
和node.is_network_authority()
。
如果您使用的是支持 C# 的 .NET 版本的 Godot,则可以使用 Nakama .NET 客户端,该客户端可以通过 NuGet 安装:
dotnet add package NakamaClient
该插件包含一些与 .NET 客户端一起使用的 C# 类,以提供与 Godot 的更深入集成:
GodotLogger
:打印到 Godot 控制台的记录器。GodotHttpAdapter
:使用 Godot 的 HTTPRequest 节点的 HTTP 适配器。GodotWebSocketAdapter
:使用 Godot 的 WebSocketClient 的套接字适配器。以下是如何使用它们的示例:
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 ) ;
注意:开箱即用的 Nakama .NET 客户端可以与您的游戏桌面版本完美配合!但是,它不适用于 HTML5 版本,除非您使用GodotHttpAdapter
和GodotWebSocketAdapter
类。
Satori 是一款游戏 liveops 服务器,支持可操作的分析、A/B 测试和远程配置。使用 Satori Godot 客户端在 Godot 游戏中与 Satori 进行通信。
Satori 仅与 Godot 4 兼容。
完整文档在线 - https://heroiclabs.com/docs/satori/client-libraries/godot/index.html
添加Satori.gd
单例(在addons/com.heroiclabs.nakama/
中)作为 Godot 中的自动加载。
创建一个客户端对象,该对象接受您作为 Satori 客户提供的 API 密钥。
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 )
然后向服务器进行身份验证以获取您的会话。
// 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." )
使用客户端,您可以获得用户所属的任何实验或功能标志。
var experiments = await _client . get_experiments_async ( session , [ "experiment1" , "Experiment2" ])
var flag = await _client . get_flag_async ( session , "FlagName" )
您还可以向服务器发送任意事件:
var _event = Event . new ( "gameFinished" , Time . get_unix_time_from_system ())
await _client . event_async ( session , _event )
开发路线图通过 GitHub 问题进行管理,并且欢迎拉取请求。如果您有兴趣改进代码,请打开一个问题来讨论更改或在社区论坛中进行讨论。
要运行测试,您需要运行服务器和数据库。大多数测试都是作为针对服务器执行的集成测试编写的。我们在测试工作流程中使用的一种快速方法是使用文档中描述的 Docker compose 文件。
此外,您需要复制(或符号链接) test_suite
文件夹内的addons
文件夹。您现在可以从 Godot 编辑器运行test_suite
项目。
要在无头机器(没有 GPU)上运行测试,您可以下载 Godot Headless 的副本并从命令行运行它。
要自动化此过程,请将无头二进制文件移至test_suite/bin/godot.elf
,并通过test_suite/run_tests.sh
shell 脚本运行测试(退出代码将报告测试失败/成功)。
cd nakama
docker-compose -f ./docker-compose-postgres.yml up
cd ..
cd nakama-godot
sh test_suite/run_tests.sh
要准备好新版本的分发,只需递归压缩 addons 文件夹(也可能添加CHANGELOG
、 LICENSE
和README.md
)。
在 unix 系统上,您可以运行以下命令(将$VERSION
替换为所需的版本号)。请记住先更新CHANGELOG
文件。
zip -r nakama- $VERSION .zip addons/ LICENSE CHANGELOG.md README.md
该项目根据 Apache-2 许可证获得许可。