GDScript로 작성된 Nakama 서버용 Godot 클라이언트입니다.
Nakama는 최신 게임과 앱을 구동하도록 설계된 오픈 소스 서버입니다. 기능에는 사용자 계정, 채팅, 소셜, 매치메이커, 실시간 멀티플레이어 등이 포함됩니다.
이 클라이언트는 서버와 함께 전체 API 및 소켓 옵션을 구현합니다. Godot Engine 4.0+
를 지원하기 위해 GDScript로 작성되었습니다.
전체 문서는 온라인에 있습니다 - 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 )
인증되면 서버는 유용한 속성을 포함하고 NakamaSession
객체로 역직렬화되는 인증 토큰(JWT)으로 응답합니다.
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는 ENet, WebSockets 및 WebRTC를 포함하여 RPC 전송을 위한 다양한 내장 백엔드를 제공합니다.
그러나 Nakama 클라이언트를 백엔드로 사용할 수도 있습니다! 이를 통해 Godot의 친숙한 고급 멀티 플레이어 API를 계속 사용할 수 있지만 RPC는 실시간 Nakama 매치를 통해 투명하게 전송됩니다.
그렇게 하려면 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 전송을 시작할 수 있고 get_tree().get_multiplayer().get_unique_id()
및 node.set_network_authority(peer_id)
및 node.is_network_authority()
.
C#을 지원하는 .NET 버전의 Godot를 사용하는 경우 NuGet을 통해 설치할 수 있는 Nakama .NET 클라이언트를 사용할 수 있습니다.
dotnet add package NakamaClient
이 애드온에는 Godot와의 심층적인 통합을 제공하기 위해 .NET 클라이언트와 함께 사용할 수 있는 일부 C# 클래스가 포함되어 있습니다.
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 클라이언트는 게임의 데스크톱 빌드에서 잘 작동합니다! 그러나 GodotHttpAdapter
및 GodotWebSocketAdapter
클래스를 사용하지 않는 한 HTML5 빌드에서는 작동하지 않습니다.
Satori는 실행 가능한 분석, 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 작성 파일을 사용하는 것입니다.
또한 test_suite
폴더 내의 addons
폴더를 복사(또는 심볼릭 링크)해야 합니다. 이제 Godot 편집기에서 test_suite
프로젝트를 실행할 수 있습니다.
GPU가 없는 헤드리스 머신에서 테스트를 실행하려면 Godot Headless 사본을 다운로드하여 명령줄에서 실행할 수 있습니다.
이 절차를 자동화하려면 헤드리스 바이너리를 test_suite/bin/godot.elf
로 이동하고 test_suite/run_tests.sh
쉘 스크립트를 통해 테스트를 실행하십시오(종료 코드는 테스트 실패/성공을 보고합니다).
cd nakama
docker-compose -f ./docker-compose-postgres.yml up
cd ..
cd nakama-godot
sh test_suite/run_tests.sh
배포할 새 릴리스를 준비하려면 애드온 폴더를 재귀적으로 압축하면 됩니다( CHANGELOG
, LICENSE
및 README.md
도 추가할 수 있음).
Unix 시스템에서는 다음 명령을 실행할 수 있습니다( $VERSION
원하는 버전 번호로 바꿈). 먼저 CHANGELOG
파일을 업데이트하는 것을 잊지 마세요.
zip -r nakama- $VERSION .zip addons/ LICENSE CHANGELOG.md README.md
이 프로젝트는 Apache-2 라이선스에 따라 라이선스가 부여됩니다.