### Install Nakama-GameLift Plugin Source: https://heroiclabs.com/docs/nakama/guides/concepts/gamelift-integration/llm.md Install the Nakama-GameLift plugin using go get. This command should be run in your Nakama project folder. ```bash go get github.com/heroiclabs/nakama-gamelift/fleetmanager ``` -------------------------------- ### Project Directory Layout Source: https://heroiclabs.com/docs/nakama/server-framework/typescript-runtime/index.html Example file and directory structure for a Nakama TypeScript server runtime project after setup. ```tree . ├── build ├── node_modules │ ├── nakama-runtime │ └── typescript ├── package-lock.json ├── package.json ├── src └── tsconfig.json ``` -------------------------------- ### Install Dependencies Source: https://heroiclabs.com/docs/nakama/server-framework/typescript-runtime/index.html Install all necessary project dependencies. ```bash npm i ``` -------------------------------- ### Initialize Game Setup Source: https://heroiclabs.com/docs/nakama/tutorials/godot/fishgame/llm.md This function is called on all clients to set up the game state, instantiate player scenes, and assign network masters. It pauses the game until all clients are ready and then initiates the game start. ```gdscript remotesync func _do_game_setup(players: Dictionary) -> void: get_tree().set_pause(true) if game_started: game_stop() game_started = true game_over = false players_alive = players reload_map() var player_number := 1 for peer_id in players: var other_player = Player.instance() other_player.name = str(peer_id) players_node.add_child(other_player) other_player.set_network_master(peer_id) other_player.set_player_skin(player_number - 1) other_player.set_player_name(players[peer_id]) other_player.position = map.get_node("PlayerStartPositions/Player" + str(player_number)).position other_player.rotation = map.get_node("PlayerStartPositions/Player" + str(player_number)).rotation other_player.connect("player_dead", self, "_on_player_dead", [peer_id]) if not GameState.online_play: other_player.player_controlled = true other_player.input_prefix = "player" + str(player_number) + "_" player_number += 1 camera.update_position_and_zoom(false) if GameState.online_play: var my_id := get_tree().get_network_unique_id() var my_player := players_node.get_node(str(my_id)) my_player.player_controlled = true # Tell the host that we've finished setup. rpc_id(1, '_finished_game_setup', my_id) else: _do_game_start() ``` -------------------------------- ### Enable and Start Nakama systemd Service Source: https://heroiclabs.com/docs/nakama/getting-started/install/linux/index.html Enable the Nakama service to start on boot and start the service immediately. ```bash sudo systemctl enable nakama sudo systemctl start nakama ``` -------------------------------- ### Initialize Tutorials System Source: https://heroiclabs.com/docs/hiro/unity/tutorials/llm.md Initializes the Tutorials system by passing in an IL logger and Nakama system. Add the initialized system to your list of systems. ```csharp var tutorialsSystem = new TutorialsSystem(logger, nakamaSystem); systems.Add(tutorialsSystem); ``` -------------------------------- ### String Starts With Substring Example Source: https://heroiclabs.com/docs/satori/concepts/segmentation/understand-audiences Checks if an installation version string begins with a specific prefix. ```Filter Expression PropertiesCustom("installVersion", "") startsWith "2.0" ``` -------------------------------- ### Initialize Nakama Module with Hello World Source: https://heroiclabs.com/docs/nakama/server-framework/go-runtime/index.html The entry point for all server-side code. Registers RPCs, hooks, and event functions. This example logs a 'Hello World!' message. ```go package main import ( "context" "database/sql" "github.com/heroiclabs/nakama-common/runtime" ) func InitModule(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, initializer runtime.Initializer) error { logger.Info("Hello World!") return nil } ``` -------------------------------- ### Download Bucketed Leaderboards Example (Go) Source: https://heroiclabs.com/docs/nakama/guides/concepts/bucketed-leaderboards/llm.md Download the full Go example file for bucketed leaderboards. ```go Download the full example file [bucketed_leaderboards.go](snippets/bucket.go) ``` -------------------------------- ### Broadcast Match Start Data (Lua) Source: https://heroiclabs.com/docs/nakama/concepts/multiplayer/authoritative Example of broadcasting match start data in Lua. Utilizes `nk.json_encode` for serialization. ```Lua local match_start_opcode = 7 match_start_data = { started = true, round_timer = 100 } dispatcher.broadcast_message(match_start_opcode, nk.json_encode(match_start_data), nil, nil) ``` -------------------------------- ### Download Full Example Source: https://heroiclabs.com/docs/nakama/guides/bucketed-leaderboards Download the complete example code for bucketed leaderboards in Go and TypeScript. ```go bucketed_leaderboards.go ``` ```typescript bucketed_leaderboards.ts ``` -------------------------------- ### Broadcast Match Start Data (TypeScript) Source: https://heroiclabs.com/docs/nakama/concepts/multiplayer/authoritative Example of broadcasting match start data in TypeScript. Uses `json.stringify` for payload serialization. ```TypeScript const matchStartOpcode = 7 const matchStartData = { started: true, roundTimer: 100 }; dispatcher.broadcastMessage(matchStartOpcode, json.stringify(matchStartData), null, null, true); ``` -------------------------------- ### Get Users HTTP Request Source: https://heroiclabs.com/docs/nakama/concepts/user-accounts/index.html Example of an HTTP GET request to retrieve user information. Parameters include IDs, usernames, and Facebook IDs. ```http GET /v2/user?ids=userid1&ids=userid2&usernames=username1&usernames=username2&facebook_ids=facebookid1 Host: 127.0.0.1:7350 Accept: application/json Content-Type: application/json Authorization: Bearer ``` -------------------------------- ### Accept a tutorial Source: https://heroiclabs.com/docs/hiro/dart/tutorials/index.html Accepts an offer to start a specific tutorial, allowing the player to begin progressing through its steps. ```APIDOC ## Accept a tutorial ### Description Accept an offer to step through a tutorial. ### Method POST ### Endpoint /tutorials/accept ### Parameters #### Request Body - **id** (string) - Required - The ID of the tutorial to accept. ### Request Example ```json { "id": "tutorial_1" } ``` ### Response #### Success Response (200) - **tutorial** (object) - The accepted tutorial object, including its current step and completion status. ### Response Example ```json { "id": "tutorial_1", "step": 0, "completed": false } ``` ``` -------------------------------- ### Broadcast Match Start Data (Go) Source: https://heroiclabs.com/docs/nakama/concepts/multiplayer/authoritative Example of marshaling and broadcasting match start data in Go. Ensure error handling for JSON marshaling. ```Go const MATCH_START_OPCODE = 7 matchStartData := &map[string]interface{} { "started": true, "roundTimer": 100, } data, err := json.Marshal(matchStartData) if err != nil { logger.Error("error marshaling match start data", err) return nil } reliable := true dispatcher.BroadcastMessage(MATCH_START_OPCODE, data, nil, nil, reliable) ``` -------------------------------- ### Build and Run Server with Docker Compose Source: https://heroiclabs.com/docs/hiro/concepts/getting-started/install/llm.md Build your Go plugin, create the Nakama container with Hiro, and start the server using Docker Compose. The first build may take a few minutes. ```bash docker compose up --build ``` -------------------------------- ### Get Account (Blocking) Source: https://heroiclabs.com/docs/nakama/client-libraries/java/llm.md A simplified, blocking example of fetching an account using the .get() method on a ListenableFuture. This is used for brevity in documentation examples but is not recommended for production game loops. ```java Account account = client.getAccount(session).get(); ``` -------------------------------- ### Initialize NakamaClient and HiroClient Source: https://heroiclabs.com/docs/hiro/unreal/getting-started/hiro-client/llm.md Create a NakamaClient instance and then use it to initialize the HiroClient. Ensure you have the Nakama plugin installed and enabled. ```cpp #include "NakamaClient.h" #include "HiroClient.h" UNakamaClient* NakamaClient = UNakamaClient::CreateDefaultClient(TEXT("defaultkey"), TEXT("localhost"), 7350, false, true); UHiroClient* HiroClient = UHiroClient::CreateDefaultClient(NakamaClient); ``` -------------------------------- ### Accept a Tutorial Source: https://heroiclabs.com/docs/hiro/godot/tutorials/llm.md Initiate a tutorial for the player. Use this when a player agrees to start a specific tutorial. Requires a TutorialAcceptRequest object with the tutorial ID. ```gdscript var request = Hiro.TutorialAcceptRequest.new() request.id = "tutorial_1" var tutorial = await hiro.tutorialsAccept(session, request) print(tutorial) ``` -------------------------------- ### Get All Tutorials Source: https://heroiclabs.com/docs/hiro/server-framework/tutorials/llm.md Retrieves all defined tutorials and the user's progress towards them. Requires user ID. ```go userId := "userId" tutorials, err := systems.GetTutorialsSystem().Get(ctx, logger, nk, userId) if err != nil { return err } ``` -------------------------------- ### Get Gem Count from Connection Account Source: https://heroiclabs.com/docs/nakama/tutorials/unity/pirate-panic/storage Example of calling the `GetGems` helper function using the `_connection.Account.Wallet` property in Unity. ```csharp GetGems(_connection.Account.Wallet); ``` -------------------------------- ### Initialize Battle Pass Systems Source: https://heroiclabs.com/docs/hiro/guides/gameplay-mechanics/battle-pass Bootstrap the game with necessary systems, including the Achievements system, for deterministic start-up. ```csharp systems.Add(nakamaSystem); // Add the Achievements system var achievementsSystem = new AchievementsSystem(logger, nakamaSystem); systems.Add(achievementsSystem); return Task.FromResult(systems); ``` -------------------------------- ### Get All Energies Source: https://heroiclabs.com/docs/hiro/typescript/energy/llm.md Retrieves the current energies and their associated timers for a player. No specific setup is required beyond having an active session. ```typescript const energyList = await hiroClient.energyGet(session); console.log(energyList); ``` -------------------------------- ### Install Nakama-i3D Fleet Manager Plugin Source: https://heroiclabs.com/docs/nakama/guides/concepts/i3d-integration/index.html Add the i3D fleet manager to your Nakama Go module using go get. ```go go get github.com/i3d/nakama-fleetmanager ``` -------------------------------- ### Initialize Go Module and Install Nakama Runtime Source: https://heroiclabs.com/docs/nakama/server-framework/go-runtime/index.html Initialize the Go module for your project and install the Nakama runtime package. Ensure you use a valid Go module path. ```bash go mod init example.com/go-project go get github.com/heroiclabs/nakama-common/runtime ``` -------------------------------- ### List Leaderboard Records API Request Source: https://heroiclabs.com/docs/nakama/concepts/leaderboards/llm.md Example HTTP GET request to list leaderboard records, including pagination with cursor. ```shell GET /v2/leaderboard/?cursor= Host: 127.0.0.1:7350 Accept: application/json Content-Type: application/json Authorization: Bearer ``` -------------------------------- ### Get All Tutorials Source: https://heroiclabs.com/docs/hiro/unity/tutorials/llm.md Retrieves all available tutorials from the system. Iterates through the tutorials to log their IDs, current/max steps, and completion status if applicable. ```csharp var tutorials = tutorialsSystem.GetAllTutorials(); foreach (var tutorial in tutorials) { Debug.Log($"Tutorial {tutorial.Id}"); Debug.Log($"Step {tutorial.Current} of {tutorial.Max}"); if (tutorial.State == TutorialState.Completed) { var completedAt = DateTimeOffset.FromUnixTimeMilliseconds(tutorial.CompleteTimeSec).DateTime; Debug.Log($"Completed at {completedAt.ToShortDateString()}"); } } ``` -------------------------------- ### List Notifications HTTP Request Source: https://heroiclabs.com/docs/nakama/concepts/notifications/llm.md Example of an HTTP GET request to list notifications, including host, accept, content-type, and authorization headers. ```shell GET /v2/notification?limit=10 Host: 127.0.0.1:7350 Accept: application/json Content-Type: application/json Authorization: Bearer ``` -------------------------------- ### Example Libraries Output Source: https://heroiclabs.com/docs/nakama/guides/server-framework/debugging-with-delve/llm.md Sample output from the 'libraries' command, showing loaded shared objects including a custom backend.so. ```bash 0. 0x7f8099127000 /lib/x86_64-linux-gnu/libdl.so.2 1. 0x7f8099106000 /lib/x86_64-linux-gnu/libpthread.so.0 2. 0x7f8098f45000 /lib/x86_64-linux-gnu/libc.so.6 3. 0x7f8099131000 /lib64/ld-linux-x86-64.so.2 4. 0x7f8062758000 /lib/x86_64-linux-gnu/libnss_files.so.2 5. 0x7f806177c000 /nakama/data/modules/backend.so ``` -------------------------------- ### Accept a Tutorial Source: https://heroiclabs.com/docs/hiro/python/tutorials Accepts and starts a specific tutorial for the player. Requires the tutorial ID. Ensure the Hiro SDK is configured and imported. ```python request = TutorialAcceptRequest() request.id = "tutorial_1" tutorial = await hiro_client.tutorials_accept(request) print(tutorial) ``` -------------------------------- ### Hello World in Lua Source: https://heroiclabs.com/docs/nakama/server-framework/lua-runtime/index.html A simple 'Hello World' example using the Nakama logger to write a message. This is a basic starting point for Lua modules. ```lua local nk = require("nakama") nk.logger_info("Hello World!") ``` -------------------------------- ### Nakama Server Startup Log with Custom Module Source: https://heroiclabs.com/docs/nakama/server-framework/go-runtime/index.html Example log output from the Nakama server indicating that a custom Go module has been successfully loaded and executed at startup. This confirms your custom logic is running. ```json { "level": "info", "ts": "....", "caller": "go-project/main.go:10", "msg": "Hello World!", "runtime": "go" } ``` -------------------------------- ### Get Users (Java) Source: https://heroiclabs.com/docs/nakama/concepts/user-accounts/index.html Fetches user data and processes it using a loop. This example demonstrates retrieving users by IDs, usernames, and Facebook IDs. ```java List ids = Arrays.asList("userid1", "userid2"); List usernames = Arrays.asList("username1", "username1"); String[] facebookIds = new String[] {"facebookid1"}; Users users = client.getUsers(session, ids, usernames, facebookIds).get(); for (User user : users.getUsersList()) { System.out.format("User id %s username %s", user.getId(), user.getUsername()); } ``` -------------------------------- ### List Groups HTTP Request Source: https://heroiclabs.com/docs/nakama/concepts/groups/llm.md This example shows how to list groups using an HTTP GET request. You can filter by name and use a cursor for pagination. ```APIDOC ## GET /v2/group ### Description Retrieves a list of groups. Supports filtering by name and pagination using a cursor. ### Method GET ### Endpoint /v2/group ### Query Parameters - **limit** (integer) - Optional - The maximum number of groups to return. - **name** (string) - Optional - A filter for group names. Supports wildcard characters. - **cursor** (string) - Optional - A cursor for fetching the next page of results. ### Request Example ```bash curl -X GET "http://127.0.0.1:7350/v2/group?limit=20&name=heroes%25&cursor=somecursor" \ -H 'Authorization: Bearer ' ``` ### Response #### Success Response (200) - **cursor** (string) - A cursor for the next page of results. - **groups** (array) - An array of group objects. - **name** (string) - The name of the group. - **id** (string) - The ID of the group. - **edgeCount** (integer) - The number of edges (e.g., members) in the group. ``` -------------------------------- ### Install Go Dependencies Source: https://heroiclabs.com/docs/hiro/concepts/getting-started/install/llm.md Run these commands to tidy up and vendor your Go dependencies. ```bash go mod tidy go mod vendor ``` -------------------------------- ### Synchronously Get a Flag Source: https://heroiclabs.com/docs/satori/client-libraries/java/llm.md For brevity in guides, the .get() method can be used to synchronously retrieve a flag. Be aware this blocks the current thread until the operation completes. ```java Flag flag = client.getFlag(session, "FlagName").get(); ``` -------------------------------- ### Accept a Tutorial Source: https://heroiclabs.com/docs/hiro/cpp/tutorials/llm.md Accept an offer to start a specific tutorial. This is used when a player decides to begin a tutorial. ```cpp void onTutorialsAccept(const Hiro::Tutorial& tutorial) { std::cout << "Successfully accepted tutorial: " << tutorial.id << '\n'; } void onError(const Nakama::NError& error) { std::cout << Nakama::toString(error.code) << ": " << error.message << '\n'; } Hiro::TutorialAcceptRequest request; request.id = "tutorial_1"; hiroClient->tutorialsAccept(session, request, onTutorialsAccept, onError); ``` -------------------------------- ### Get All Tutorials Source: https://heroiclabs.com/docs/hiro/godot/tutorials/llm.md Retrieve the list of available tutorials and the player's current progress step for each. This is useful for initializing the tutorial system for a player. ```gdscript var tutorial_list = await hiro.tutorialGet(session) print(tutorial_list) ``` -------------------------------- ### Get Leaderboard Records Cursor by Rank Source: https://heroiclabs.com/docs/nakama/server-framework/typescript-runtime/function-reference/index.html Builds a cursor to fetch leaderboard records starting at a specific rank. Only available if rank cache is not disabled for the leaderboard. ```typescript let id = '4ec4f126-3f9d-11e7-84ef-b7c182b36521'; let rank = 1; let overrideExpiry = 3600; try { result = nk.leaderboardRecordsListCursorFromRank(id, rank, overrideExpiry); } catch(error) { // Handle error } ``` -------------------------------- ### List Leaderboard Records HTTP Request Source: https://heroiclabs.com/docs/nakama/concepts/leaderboards/index.html Example HTTP GET request to list leaderboard records. Requires the leaderboard ID and session token for authorization. ```http GET /v2/leaderboard/ Host: 127.0.0.1:7350 Accept: application/json Content-Type: application/json Authorization: Bearer ``` -------------------------------- ### Setup and Connect Nakama Socket Source: https://heroiclabs.com/docs/nakama/client-libraries/unreal/llm.md Set up a real-time client from the Nakama Client and connect to the server. Define delegates for connection success and error callbacks. ```cpp RealtimeClient = Client->SetupRealtimeClient(Session); FOnRealtimeClientConnected ConnectionSuccessDelegate; ConnectionSuccessDelegate.AddDynamic(this, &ASagiShiActor::OnRealtimeClientConnectionSuccess); FOnRealtimeClientError ConnectionErrorDelegate; ConnectionErrorDelegate.AddDynamic(this, &ASagiShiActor::OnRealtimeClientConnectionError); RealtimeClient->Connect(ConnectionSuccessDelegate, ConnectionErrorDelegate); ``` -------------------------------- ### List Notifications HTTP Request Source: https://heroiclabs.com/docs/nakama/concepts/notifications/llm.md Example HTTP GET request to list notifications with a specified limit and cursor. Includes necessary headers for authentication and content type. ```shell GET /v2/notification?limit=100&cursor= Host: 127.0.0.1:7350 Accept: application/json Content-Type: application/json Authorization: Bearer ``` -------------------------------- ### Full Session Management and Storage Example Source: https://heroiclabs.com/docs/nakama/client-libraries/cocos2d-js/index.html This example shows how to manage user sessions by restoring from local storage or authenticating via email. It also demonstrates writing data to Nakama storage. ```javascript var client = new nakamajs.Client("defaultkey"); var currentSession = null; function storeSession(session) { cc.sys.localStorage.setItem("nakamaToken", session.token); cc.log("Session stored."); } function getSessionFromStorage() { return cc.sys.localStorage.getItem("nakamaToken"); } function restoreSessionOrAuthenticate() { const email = "hello@example.com"; const password = "somesupersecretpassword"; var session = null; try { var sessionString = getSessionFromStorage(); if (sessionString && sessionString !== "") { session = nakamajs.Session.restore(sessionString); var currentTimeInSec = new Date() / 1000; if (!session.isexpired(currentTimeInSec)) { cc.log("Restored session. User ID: ", session.user_id); return Promise.resolve(session); } } return new Promise(function(resolve, reject) { client.authenticateEmail(email, password) .then(function(session) { storeSession(session); cc.log("Authenticated successfully. User ID:", session.user_id); resolve(session); }, function(error) { cc.error("authenticate failed:", JSON.stringify(error)); reject(error); }); }); } catch(e) { cc.log("An error occurred while trying to restore session or authenticate user:", JSON.stringify(e)); return Promise.reject(e); } } restoreSessionOrAuthenticate().then(function(session) { currentSession = session; return client.writeStorageObjects(currentSession, [{ "collection": "collection", "key": "key1", "value": {"jsonKey": "jsonValue"} }]); }).then(function(writeAck) { cc.log("Storage write was successful - ack:", JSON.stringify(writeAck)); }).catch(function(e) { cc.log("An error occurred:", JSON.stringify(e)); }); ``` -------------------------------- ### Client Initialization Source: https://heroiclabs.com/docs/satori/client-libraries/dart/llm.md Demonstrates how to create an instance of the Satori Client, which is the entry point for accessing Satori features. It requires server connection details. ```APIDOC ## Client Initialization ### Description Initializes the Satori Client to connect to a Satori Server. It's recommended to have one client per server per game. ### Method `getSatoriClient` ### Parameters - **host** (string) - Required - The hostname or IP address of the Satori Server. - **port** (int) - Required - The port number the Satori Server is listening on. - **ssl** (bool) - Required - Whether to use SSL for the connection. - **apiKey** (string) - Required - The API key for authentication. ### Request Example ```dart final client = getSatoriClient( host: '127.0.0.1', port: 7450, ssl: false, apiKey: 'apikey', ); ``` ``` -------------------------------- ### List Leaderboard Records Around Owner (C++) Source: https://heroiclabs.com/docs/nakama/concepts/leaderboards/llm.md Call the listLeaderboardRecordsAroundOwner function in C++ to get records near a specified owner. This example includes a success callback. ```cpp string leaderboardId = "level1"; string ownerId = "some user ID"; int32_t limit = 100; client->listLeaderboardRecordsAroundOwner(session, leaderboardId, ownerId, limit, successCallback); ``` -------------------------------- ### HTTP API Endpoint for Listing Tournament Records Source: https://heroiclabs.com/docs/nakama/concepts/tournaments Example HTTP GET request to list tournament records around a specific owner. Includes required headers and path parameters. ```http GET /v2/tournament//owner/?limit= Host: 127.0.0.1:7350 Accept: application/json Content-Type: application/json Authorization: Bearer ``` -------------------------------- ### Initialize Google System Source: https://heroiclabs.com/docs/hiro/concepts/integrations/llm.md Initialize the Google system by adding it to the system list. ```csharp var googleSystem = new GoogleSystem(); system.add(googleSystem); ``` -------------------------------- ### Accept Tutorial Source: https://heroiclabs.com/docs/hiro/server-framework/tutorials/llm.md Marks a tutorial as accepted by the user. Requires tutorial ID and user ID. ```go tutorialId := "tutorialId" userId := "userId" tutorial, err := systems.GetTutorialsSystem().Accept(ctx, logger, nk, tutorialId, userId) if err != nil { return err } ``` -------------------------------- ### REST API Request for Channel Messages Source: https://heroiclabs.com/docs/nakama/concepts/chat/index.html Example of a direct HTTP GET request to list channel messages, including necessary headers like Host, Accept, Content-Type, and Authorization. ```http GET /v2/channel/?forward=true&limit=10&cursor= Host: 127.0.0.1:7350 Accept: application/json Content-Type: application/json Authorization: Bearer ``` -------------------------------- ### Get Leaderboard Configuration (Deprecated) Source: https://heroiclabs.com/docs/hiro/typescript/leaderboards/llm.md Retrieves basic configuration data for leaderboards. This method is deprecated in Hiro 1.33 and later; use `leaderboardList` instead. This example is for Hiro 1.32 and earlier. ```typescript const leaderboardConfigList = await hiroClient.leaderboardsConfigGet(session); console.log(leaderboardConfigList); ``` -------------------------------- ### Nakama Configuration Example Source: https://heroiclabs.com/docs/nakama/getting-started/configuration/llm.md A comprehensive example of a Nakama configuration file, showcasing various settings for different modules. ```yaml name: nakama-node-1 data_dir: "./data/" logger: stdout: false level: "warn" file: "/tmp/path/to/logfile.log" rotation: false max_size: 100 max_age: 0 max_backups: 0 local_time: false compress: false metrics: reporting_freq_sec: 60 namespace: "" prometheus_port: 7354 database: address: - "root@localhost:26257" conn_max_lifetime_ms: 0 max_open_conns: 0 max_idle_conns: 100 runtime: env: - "example_apikey=example_apivalue" - "encryptionkey=afefa==e332*u13=971mldq" path: "/tmp/modules/folders" http_key: "defaulthttpkey" socket: server_key: "defaultkey" port: 7350 max_message_size_bytes: 4096 # bytes read_timeout_ms: 10000 write_timeout_ms: 10000 idle_timeout_ms: 60000 write_wait_ms: 5000 pong_wait_ms: 10000 ping_period_ms: 8000 # Must be less than pong_wait_ms outgoing_queue_size: 16 session: encryption_key: "defaultencryptionkey" token_expiry_sec: 60 refresh_encryption_key: "defaultrefreshencryptionkey" refresh_token_expiry_sec: 3600 social: steam: publisher_key: "" app_id: 0 console: port: 7351 username: "admin" password: "password" cluster: join: - "10.0.0.2:7352" - "10.0.0.3:7352" gossip_bindaddr: "0.0.0.0" gossip_bindport: 7352 rpc_port: 7353 local_priority: true work_factor_interval_ms: 1000 tracker: max_delta_sizes: - 100 - 1000 - 10000 matchmaker: max_tickets: 2 interval_sec: 15 max_intervals: 3 iap: apple: shared_password: "password" google: client_email: "email@google.com" private_key: "pk" huawei: public_key: "pk" client_id: "id" client_secret: "secret" ``` -------------------------------- ### Initialize Player Currencies and Items Source: https://heroiclabs.com/docs/hiro/guides/gameplay-mechanics/quests/index.html Configuration for the Hiro Economy system, defining initial currencies (coins, gems, tokens) and items for a player. This example starts the player with a blank slate. ```json { "initialize_user": { "currencies": { "coins": 0, "gems": 0, "tokens": 0 }, "items": {} }, "store_items": {} } ``` -------------------------------- ### Initialize Hiro Systems and Access Them Source: https://heroiclabs.com/docs/hiro/server-framework/introduction/core-functions-and-hooks/llm.md Example of initializing Hiro systems and passing the initialized systems object to other components that require access to Hiro's functionalities. Ensure all necessary configurations and paths are correctly provided. ```go // ... systems, err := hiro.Init(ctx, logger, nk, initializer, binPath, hiroLicense, hiro.WithBaseSystem(fmt.Sprintf("base-system-%s.json", env), true), hiro.WithEnergySystem(fmt.Sprintf("base-energies-%s.json", env), true), hiro.WithStatsSystem(fmt.Sprintf("base-stats-%s.json", env), true)) if err != nil { return err } staminaPersonalizer, err := NewStaminaPersonalizer(nk, systems.GetStatsSystem(), "stamina-personalizer.json") if err != nil { return err } // ... ``` -------------------------------- ### Initialize Nakama Module with Hello World Source: https://heroiclabs.com/docs/nakama/server-framework/typescript-runtime/index.html This is the entry point for your server code. It registers RPCs, hooks, and event functions. This example logs a 'Hello World!' message. ```typescript let InitModule: nkruntime.InitModule = function(ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, initializer: nkruntime.Initializer) { logger.info("Hello World!"); } ``` -------------------------------- ### Update Player Identity with Satori SDK (Python) Source: https://heroiclabs.com/docs/satori/guides/satori-databricks/index.html Example of updating a player's custom property 'dbChurnPrediction' in Satori using the Python SDK. Ensure the Satori SDK is installed and configured. ```python from satori_sdk import SatoriClient # Initialize Satori client satori_client = SatoriClient(api_key="YOUR_API_KEY", game_id="YOUR_GAME_ID") player_id = "20421bc3-e1ea-4c52-ad99-6e7dbf0c502a" prediction_result = "PredictionResult" # Update player identity with custom property try: response = satori_client.update_identity(player_id, properties={ "custom": { "dbChurnPrediction": prediction_result } }) print(f"Successfully updated identity {player_id}: {response}") except Exception as e: print(f"Error updating identity {player_id}: {e}") # Example of reading player data try: player_data = satori_client.get_identity(player_id) print(f"Player data for {player_id}: {player_data}") except Exception as e: print(f"Error getting identity {player_id}: {e}") # Example of creating a custom property if it doesn't exist try: custom_properties = satori_client.list_custom_properties() if "dbChurnPrediction" not in custom_properties: satori_client.create_custom_property(name="dbChurnPrediction", type="string") print("Custom property 'dbChurnPrediction' created.") else: print("Custom property 'dbChurnPrediction' already exists.") except Exception as e: print(f"Error managing custom property: {e}") # Example of sending an event try: event_data = { "eventType": "player_prediction", "data": { "prediction": prediction_result } } response = satori_client.send_event(player_id, event_data) print(f"Successfully sent event for {player_id}: {response}") except Exception as e: print(f"Error sending event for {player_id}: {e}") # Example of querying identities based on a custom property try: query_results = satori_client.query_identities(filter=f"properties.custom.dbChurnPrediction = '{prediction_result}'") print(f"Identities matching prediction '{prediction_result}': {query_results}") except Exception as e: print(f"Error querying identities: {e}") # Example of deleting a custom property # Be cautious when deleting properties as it's irreversible # try: # satori_client.delete_custom_property(name="dbChurnPrediction") # print("Custom property 'dbChurnPrediction' deleted.") # except Exception as e: # print(f"Error deleting custom property: {e}") # Example of updating an identity with multiple custom properties try: response = satori_client.update_identity(player_id, properties={ "custom": { "dbChurnPrediction": "AnotherPrediction", "anotherCustomProperty": "someValue" } }) print(f"Successfully updated identity {player_id} with multiple properties: {response}") except Exception as e: print(f"Error updating identity {player_id} with multiple properties: {e}") # Example of getting a list of all custom properties try: all_custom_props = satori_client.list_custom_properties() print(f"All custom properties: {all_custom_props}") except Exception as e: print(f"Error listing custom properties: {e}") # Example of updating an identity with a null value for a custom property try: response = satori_client.update_identity(player_id, properties={ "custom": { "dbChurnPrediction": None } }) print(f"Successfully updated identity {player_id} with null prediction: {response}") except Exception as e: print(f"Error updating identity {player_id} with null prediction: {e}") # Example of getting identity history try: history = satori_client.get_identity_history(player_id) print(f"History for identity {player_id}: {history}") except Exception as e: print(f"Error getting identity history {player_id}: {e}") # Example of batch updating identities try: batch_updates = [ {"id": "player1_id", "properties": {"custom": {"dbChurnPrediction": "BatchPred1"}}}, {"id": "player2_id", "properties": {"custom": {"dbChurnPrediction": "BatchPred2"}}} ] response = satori_client.batch_update_identities(batch_updates) print(f"Batch update response: {response}") except Exception as e: print(f"Error during batch update: {e}") # Example of deleting an identity # Use with extreme caution # try: # response = satori_client.delete_identity(player_id) # print(f"Successfully deleted identity {player_id}: {response}") # except Exception as e: # print(f"Error deleting identity {player_id}: {e}") # Example of creating a new identity try: new_identity_id = "new_player_id_123" response = satori_client.create_identity(new_identity_id, properties={ "custom": { "dbChurnPrediction": "InitialPrediction" } }) print(f"Successfully created identity {new_identity_id}: {response}") except Exception as e: print(f"Error creating identity {new_identity_id}: {e}") # Example of updating an identity with a list property try: response = satori_client.update_identity(player_id, properties={ "custom": { "playerTags": ["new_tag", "another_tag"] } }) print(f"Successfully updated identity {player_id} with list property: {response}") except Exception as e: print(f"Error updating identity {player_id} with list property: {e}") # Example of updating an identity with a dictionary property try: response = satori_client.update_identity(player_id, properties={ "custom": { "playerStats": {"level": 10, "score": 1000} } }) print(f"Successfully updated identity {player_id} with dictionary property: {response}") except Exception as e: print(f"Error updating identity {player_id} with dictionary property: {e}") # Example of getting identity by external ID try: external_id = "external_player_123" identity_by_external = satori_client.get_identity_by_external_id(external_id) print(f"Identity for external ID {external_id}: {identity_by_external}") except Exception as e: print(f"Error getting identity by external ID {external_id}: {e}") # Example of updating an identity using a dictionary for properties try: update_data = { "properties": { "custom": { "dbChurnPrediction": "UpdatedPrediction" } } } response = satori_client.update_identity(player_id, update_data) print(f"Successfully updated identity {player_id} using dictionary: {response}") except Exception as e: print(f"Error updating identity {player_id} using dictionary: {e}") # Example of listing all properties for an identity try: all_props = satori_client.get_identity_properties(player_id) print(f"All properties for identity {player_id}: {all_props}") except Exception as e: print(f"Error getting all properties for identity {player_id}: {e}") # Example of deleting a custom property from an identity try: response = satori_client.update_identity(player_id, properties={ "custom": { "dbChurnPrediction": None } }, delete_properties=["custom.dbChurnPrediction"]) print(f"Successfully deleted custom property from identity {player_id}: {response}") except Exception as e: print(f"Error deleting custom property from identity {player_id}: {e}") # Example of updating an identity with a boolean property try: response = satori_client.update_identity(player_id, properties={ "custom": { "isPremiumUser": True } }) print(f"Successfully updated identity {player_id} with boolean property: {response}") except Exception as e: print(f"Error updating identity {player_id} with boolean property: {e}") # Example of updating an identity with a numeric property try: response = satori_client.update_identity(player_id, properties={ "custom": { "playerLevel": 15 } }) print(f"Successfully updated identity {player_id} with numeric property: {response}") except Exception as e: print(f"Error updating identity {player_id} with numeric property: {e}") ``` -------------------------------- ### Example Call to Start Matchmaking Source: https://heroiclabs.com/docs/nakama/tutorials/godot/fishgame/llm.md Demonstrates how to call `OnlineMatch.start_matchmaking` with specific matchmaking criteria, including minimum player count, string properties like region, and numeric properties like rank. ```gdscript OnlineMatch.start_matchmaking(Online.nakama_socket, { # The default minimum is 2, we can increase that to 3 to find a 3-player match. min_count = 3, # We can tell the matchmaker about string or numeric properties of this player. string_properties = { region = 'europe', }, numeric_properties = { rank = 8, }, # The query requires a player in the same region and similar rank. query = '+region:europe +rank:>=7 +rank:<=9' }) ``` -------------------------------- ### Start Nakama server with PostgreSQL (Powershell/Bash) Source: https://heroiclabs.com/docs/nakama/getting-started/install/windows/index.html Starts the Nakama server using PostgreSQL. Requires specifying the database address, user, and password. ```bash ./nakama.exe --database.address postgres:password@127.0.0.1:5432 ``` -------------------------------- ### Unity HiroCoordinator Setup with NetworkMonitor Source: https://heroiclabs.com/docs/hiro/unity/offline-support Sets up the HiroCoordinator in Unity, including various network probes for monitoring connectivity. This example demonstrates using multiple probes for comprehensive network status detection. ```csharp private INetworkMonitor _monitor; protected override Task CreateSystemsAsync() { // Keep reference to manually change `Online` property when desired. var forceProbe = new ForceNetworkProbe(true); // Simply check `Application.internetReachability`. var reachabilityProbe = InternetReachabilityNetworkProbe.Default; // Interval in seconds before trying to re-sync with Nakama after going offline. var nakamaProbe = new NakamaClientNetworkProbe(TimeSpan.FromSeconds(60)); // Add the probes in the order you want them to be processed. _monitor = new NetworkMonitor(forceProbe, reachabilityProbe, nakamaProbe); // Detect when entering/exiting offline mode. _monitor.ConnectivityChanged += (_, args) => { Instance.Logger.InfoFormat($"Network is online: {args.Online}"); }; // Pass the nakamaProbe here to allow it to update when interacting with your Nakama server. var nakamaSystem = new NakamaSystem(logger, scheme, host, port, serverKey, NakamaAuthorizerFunc(_monitor), nakamaProbe); // Remember to pass the NetworkMonitor to allow your systems to function while offline. var systems = new Systems("HiroSystemsContainer", _monitor, logger); return Task.FromResult(systems); } ``` -------------------------------- ### Initialize Hiro Systems and Nakama Connection Source: https://heroiclabs.com/docs/sample-projects/unity/hiro-challenges/index.html Sets up the Nakama client and registers essential Hiro systems including Nakama, Challenges, and Economy systems. This is part of the coordinator's setup process. ```csharp protected override Task CreateSystemsAsync() { var client = new Client(scheme, host, port, serverKey); var nakamaSystem = new NakamaSystem(logger, client, NakamaAuthorizerFunc()); var systems = new Systems(nameof(HiroChallengesCoordinator), monitor, storage, logger); systems.Add(nakamaSystem); systems.Add(new ChallengesSystem(logger, nakamaSystem)); // We need to register the EconomySystem to power rewards and the wallet systems.Add(new EconomySystem(logger, nakamaSystem, EconomyStoreType.Unspecified)); return Task.FromResult(systems); } ``` -------------------------------- ### Get Tutorials System Source: https://heroiclabs.com/docs/hiro/server-framework/introduction/core-functions-and-hooks/index.html Retrieves a reference to the Tutorials System. Use this when you need to manage or interact with tutorial flows. ```go systems.GetTutorialsSystem() ``` -------------------------------- ### Synchronously Get Result with .get() Source: https://heroiclabs.com/docs/nakama/client-libraries/java/index.html For simplicity in examples, the .get() method can be used to block the current thread and retrieve the result of an asynchronous operation. Use with caution in production environments to avoid blocking the main thread. ```java Account account = client.getAccount(session).get(); ```