# FieldWalker

## Diarkis Unity SDK Sample Application

This is a sample application based on Unity Engine provided by the network middleware, Diarkis. It includes various features such as MatchMake, DirectMessage, and player-to-player data synchronization using different protocols (UDP, TCP, P2P). For more details about Diarkis products, please refer to the [Diarkis Website](https://help.diarkis.io/).

## Folder Description

* `Core` Install the Diarkis `C#` SDK
  * `Client` Diarkis Module (C# classes and helpers for using the Diarkis Core Library)
    * `Data` Data structure related classes
    * `Events` Event related classes
    * `Logging` Classes related to the logging system
    * `Modules` Module-base classes (code interacting with Diarkis Core Library)
    * `System` System related classes (like memory management)
    * `Utils` Various helpers for using Diarkis types
  * `Interop` Auto-generated `C#` files to call Diarkis Native Code (modifying these files is not recommended)
  * `CustomCommands` Developers can define custom commands using the files here
    * `json_definitions` JSON files defining structures for custom commands
    * `custom` JSON files defining structures for custom commands
  * `Libraries` Diarkis Native Code made in `C++` (Diarkis Core API)
* `Documentation` This document
* `Plugin` Diarkis plugin scripts
  * `Callbacks` Scripts to register callbacks to Diarkis events
  * `Common` Scripts common to each scene (including the singleton class DiarkisNetworkManager interfacing with Diarkis SDK)
    * `MainGame` Scripts for the MainGame scene (synchronization of players in a 3D environment)
* `Sample` Diarkis sample scripts
  * `Misc` Miscellaneous files (lighting, input system, etc.)
  * `Models` 3D model files
    * `Animations` Animation files for characters
    * `Materials` Material files
  * `Prefabs` Prefab files (e.g., DiarkisPlayer, Grid, etc.)
  * `Scenes` Scene files for Unity.
  * `Scripts` Unity related scripts
    * `MainGame` Scripts for the MainGame scene (synchronization of players in a 3D environment)
    * `SceneManagers` Scene-specific classes
    * `UI` User interface scripts (buttons, toggles, etc.)
* `Textures` Image files

## Loading the Project

In the Unity project, open the package manager with `Window>Package Manager`, click `+`, then `Add Package From Disk`, and select the package.json file found at the root of the Diarkis sample folder.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-4ba5db0edf6dc2906c43739efee7384b8ce9e4f9%2Fimport-package.png?alt=media)

It is recommended to use the LTS version of Unity (as of the latest update, 2022.3.20f1).\
You can now open the project in `Unity Editor`.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-27325e9056649439e806066988ddc52cd7e80e9f%2FUnityEditor.png?alt=media)

Select the title scene file (`Assets/Scenes/DiarkisSample_1_Title.unity`). You can run the sample by clicking the play button from the toolbar.

### Library Security Error on MacOS

Users loading the project on MacOS might see a pop-up notification stating that the library cannot be trusted. In this case, open `System Preferences>Privacy & Security` without closing the window and press `Allow Anyway`. You may need to apply this to each library (only once for each). Failing to do so will prevent the Diarkis library from running, and the sample will display runtime errors.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-826c588982383b53703b99b3562d57f36bc4521f%2Fmacos-popup.png?alt=media)

### Disabling Recompile on Play Mode

Currently, Diarkis does not correctly handle code recompilation during play mode (due to the usage of unmanaged resources).\
It is recommended to disable this feature in the editor via `Edit > Preferences > General > Script Change While Playing` and select `Recompile after playing` or `Stop playing and recompile`. ![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-63e99ede536a6b228ad413d1e7540d8e9d85206b%2Fdisable_recompile-in-play-mode.png?alt=media)

## Scene Explanation

### Title

This scene is the initial sample scene and can provide various inputs to set up the connection with the Diarkis server.

| Item       | Description                                                     | Example                                                                      |
| ---------- | --------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| Host       | The EndPoint URL of the Diarkis Http server                     | asia-northeast1.diarkis.io (http\:// is not required) / 192.168.XXX.XXX:7000 |
| ClientKey  | Client Key (specify if needed)                                  | XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX                                         |
| UID        | Unique User ID                                                  | Diarkis203                                                                   |
| RandomUID  | Randomly auto-generate a unique User ID (unique GUID)           | 0f0b66aa-8d45-4505-9208-c41d975a0c65                                         |
| ServerType | Specify the communication protocol of the Diarkis server to use | UDP or TCP                                                                   |

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-f1d73b67dadce681b96ca65342cc0e57f704d948%2FTitleScene.png?alt=media)

### SelectFeature

From this screen, you can choose features related to each Diarkis module.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-0f887fbb4acccfc9a8513a3fee150aafd647edbf%2FFeatureSelection.png?alt=media)

### Room

This screen uses the `Diarkis Room Module`. You can enter a room using Create, Join, or RandomJoin from this screen.

| Item               | Description                                                                                                   | Example |
| ------------------ | ------------------------------------------------------------------------------------------------------------- | ------- |
| MaxMember          | Maximum number of members in the Room                                                                         | 4       |
| AllowEmpty         | Allow the existence of a room when no user is present in it.                                                  | true    |
| TTL                | Room's survival time after it's left with no members.                                                         | 60      |
| Interval           | Sending interval on the server for Broadcast and MessageTo messages; messages are buffered for this interval. | 200     |
| Join Existing Room | Specify RoomID to join. (Do not use the above setting)                                                        |         |
| Join Random Room   | Join a random room using the settings above, or create a new room if no existing room is found.               |         |
| Create Room        | Create and join a room using the settings above.                                                              |         |

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-a80251719e1e487d88fbbd32f31b6b58ec9f1313%2FRoomScene.png?alt=media)

### MainGame - Room

This screen appears upon successfully joining a `Room`. Message exchange through the `Diarkis Room Module` synchronizes the position of players and objects.

| Item               | Description                                                                                                                                                   | Example                      |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |
| My UID             | UserID for the local character                                                                                                                                | Diarkis-Test                 |
| Room ID            | ID of the Room in which you are entering                                                                                                                      | 17b39a74e5fff52c7f0000011fa4 |
| Owner UID          | User ID of the Room Owner                                                                                                                                     | Diarkis-Test                 |
| Members            | Members currently entering the Room                                                                                                                           | Diarkis-Test, ...            |
| Broadcast/Send     | Send a message to everyone in the Room. Specifying a User ID sends the message only to that user                                                              |                              |
| Leave              | Leave the Room and return to the previous screen                                                                                                              |                              |
| Start P2P          | Initializes the P2P communication with other Room members. After setting up, messaging is done using the `Diarkis P2P Module`, improving communication speed. |                              |
| Create Sphere/Cube | Creates a new object near the player and synchronizes its position                                                                                            |                              |
| Clear All Objects  | Deletes all created Objects within the Room                                                                                                                   |                              |
| Clear My Objects   | Deletes all Objects created by you within the Room                                                                                                            |                              |

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-0b5f5d0ed974dd4fa16b36cd3a37dabf57376950%2FRoomMainGame.png?alt=media)

### MainGame - Field

This screen displays a 3D representation of the `Diarkis Field Module`. Field communication does not require pre-commands like Join or Create. Only one Field exists per server type, and a user can only exist at one position within it at a time.

| Item         | Description                                                                                    | Example      |
| ------------ | ---------------------------------------------------------------------------------------------- | ------------ |
| My UID       | UserID for the local character                                                                 | Diarkis-Test |
| Server Count | Number of Diarkis servers in the mesh network affects the number of Grids dividing the ground. | 4            |
| Field Size   | Size of the Field; changes the overall Field size and the Grid size dividing it.               | 4500         |
| Grid Size    | Size of one Grid, calculated from Field Size and Server Count.                                 | 2250         |
| Leave        | Leave the Field and return to the previous scene.                                              |              |

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-b9775d938fde0a7a7061e6c897e3dcd1d40ab0f6%2FField.png?alt=media)

### MatchMaker

This screen allows you to issue a `IssueTicket` using the `Diarkis MatchMaker Module` and wait for matching with other users from the server. Upon completing the match, you can broadcast messages to other `Ticket members`.

| Item            | Description                                                                                                                                                                                         | Example                                             |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
| TicketType      | Specify the type of ticket to issue. In the basic version of the Diarkis Template Server, only Ticket Type 0 is implemented. Some server-side development is required to handle other ticket types. | 0                                                   |
| Issue Ticket    | Issue a MatchMaking IssueTicket to the server.                                                                                                                                                      |                                                     |
| Cancel          | Cancel an IssueTicket.                                                                                                                                                                              |                                                     |
| Status          | Matching status.                                                                                                                                                                                    | Not Started / Waiting For Match / Complete / Failed |
| Ticket Owner ID | UserID of the owner of the completed ticket.                                                                                                                                                        |                                                     |
| Members         | Members of the completed ticket.                                                                                                                                                                    |                                                     |
| Message         | Broadcast a message to other Members of the Ticket.                                                                                                                                                 |                                                     |

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-1efe646d21607b5676b3a635d07bbfe281f0cb0b%2FMatchMaker.png?alt=media)

### Group

The `Diarkis Group Module` allows you to create or join a random Group from this screen, and broadcast messages to other Group members.

| Item           | Description                                |
| -------------- | ------------------------------------------ |
| Group ID       | The Group ID you are participating in      |
| Message Button | Broadcast a message to other Group members |

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-c375f2509476784276d8fec7a0384331c4c866c3%2FGroup.png?alt=media)

### Direct Message

The `Diarkis DM Module` can be used on this screen to send Unicast messages directly to other members.

| Item           | Description                                                     |
| -------------- | --------------------------------------------------------------- |
| My UID         | Your UserID                                                     |
| Recipient ID   | UserID of the user to whom the message will be sent             |
| Message Button | Send a Direct Message to the user specified by the Recipient ID |

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-4d4097c158967644879a37b3b5df3067384cecd3%2FDM.png?alt=media)

## Class Description

### [DiarkisNetworkManager](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Scripts/Plugin/Common/DiarkisNetworkManager.cs)

This class is a MonoBehaviour singleton class and must remain active as long as the user wishes to use Diarkis features in the Unity Project. It can be called statically to expose Diarkis module objects.

**Usage Example:**

```csharp
if (!DiarkisNetworkManager.IsConnected()) // check if the client is not yet connected to Diarkis
{
    DiarkisNetworkManager.Instance.ServerType = Diarkis.ServerType.UDP; // set the protocol to UDP
    DiarkisNetworkManager.Instance.HttpHost = "127.0.0.1:7000"; // set the server address
    DiarkisNetworkManager.Instance.ClientKey = _clientKeyInputField.text; // set the client Key
    DiarkisNetworkManager.Instance.UID = "John Doe"; //set the user ID
    DiarkisNetworkManager.Connect(); // initiate Connection to Diarkis
}
```

The inspector UI includes various options to set up Diarkis options from the editor:

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-7dfe70d7315ae73b0f4857eea26e13d682e2fe17%2FNetworkManagerInspector.png?alt=media)

### Events

Diarkis API uses its own event system. When specific actions within the Diarkis module are completed, events are triggered by the related module, and all registered callbacks are invoked in the [EventHandler](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Events/DiarkisEventHandler.cs). Each event and its parameter signatures are located in this class.

**Example of Event Registration:**

```csharp
protected override void Start()
{
  DiarkisEventHandler handler = DiarkisNetworkManager.GetEventHandler();
  handler.RegisterCallback(DiarkisEventType.UDPConnect, (System.Action<DiarkisConnectionEventArgs>)((args) => { OnConnect(args); }), this);
}

public void OnConnect(DiarkisConnectionEventArgs args)
{
    if (args.GetStatus() == DiarkisConnectStatus.DCS_Success)
    {
        Logger.Debug("Connection Success");
    }
    else
    {
        Logger.Error("Connection Failed");
    }
}
```

The [DiarkisCallbackDispatcher](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Scripts/Plugin/Callbacks/DiarkisCallbackDispatcher.cs) MonoBehaviour class allows you to register events from the Editor user interface without writing a single line of code. It is also useful for remembering the event’s type signature.

For example, the following setting behaves similarly to the above code.

![DiarkisCallbackDispatcher Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-f1a4ce97e2837ddfa76f890328fc70aa02e50517%2FDiarkisCallbackDispatcherInspector.png?alt=media)

### Logging

The Diarkis logging system is based on two classes: [DiarkisLogger](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Logging/DiarkisLogger.cs) and [DiarkisLoggingFactory](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Logging/DiarkisLoggerFactory.cs).

`DiarkisLogger` instances are created by `DiarkisLoggerFactory` and are used to log information at different log levels. These loggers provide methods for logging messages, warnings, errors, and other pertinent information regarding the execution of the application.

`DiarkisLoggerFactory` is responsible for creating loggers within the native code, providing Logger instances to different modules within the Diarkis framework. The log function provided in LoggerFactory's constructor can be configured to control the output destination, log level filtering, and formatting options, allowing developers to tailor the logging behavior to their specific needs.

**Usage Example:**

```csharp
    class Program
    {
        static void Main(string[] args)
        {
            var logSeverity = DiarkisLoggerSeverity.Debug;
            var logFileStream = DiarkisUtils.GetFileStreamWriter("./", "diarkis-cs-sample-logs.txt");
            var logAction = new Action<string>((str) =>
            {
                if (str.Contains("\n"))
                {
                    Console.Write(str);
                    logFileStream.Write(str);
                }
                else
                {
                    Console.WriteLine(str);
                    logFileStream.WriteLine(str);
                }
            });
            var loggerFactory = new Diarkis.DiarkisLoggerFactory(logSeverity, logAction);
            DiarkisLogger = loggerFactory.CreateLogger();
            var logger1 = (DiarkisLogger)loggerFactory.CreateLogger("ExampleLogger1");
            var logger2 = (DiarkisLogger)loggerFactory.CreateLogger("ExampleLogger2");
            logger1.Error("this is an error");
            logger2.Debug("this is a Debug log");
            logger2.Verbose("the Debug Log is not displayed because severity level is too high");
            var eventHandler = new DiarkisEventHandler();
            Diarkis.DiarkisInterface diarkis = new Diarkis.DiarkisInterface(loggerFactory, ServerType.UDP, eventHandler);
        }
    }
```

**Output Example:**

```
2024-02-01 15:39:32[FAIL][ExampleLogger1]this is an error
2024-02-01 15:39:32[DEBUG][ExampleLogger2]this is a Debug log
```

Note: The code above also creates a file at `./diarkis-cs-sample-logs.txt` and registers the output.

**Log Level Hierarchy:**

```csharp
public enum DiarkisLoggerSeverity {
  Trace = 0,
  Verbose,
  Debug,
  Info,
  Warning,
  Error,
  Fatal,
  None
}
```

#### Logger Manager Inspector

The `NetworkManager` inspector also includes various fields for easily configuring the logger. For example, you can set different log severities based on the logger's category or display logs on the game screen.

![DiarkisCallbackDispatcher Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-b03781485099bf6518ce79d6edd95c8b6c287572%2Flogger-inspector.png?alt=media)

### Diarkis Core Library

The Diarkis Core Library is a DLL made in `C++`. Automatically generated .cs wrapper files `Core-wrapped` allow the use of `C++` native code in `C#`.

### Diarkis Module

Diarkis Module is part of the Diarkis `C#` SDK and is independent of Unity, allowing it to be used in pure `C#` console applications.

#### [DiarkisInterface](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Modules/DiarkisInterface.cs)

This is not strictly a module but a class that functions as an interface containing all Diarkis Modules at once. It is a member of the `DiarkisNetworkManager` Unity class but can also be used in a plain `C#` context. You need one `DiarkisInterface` per connection to a Diarkis server. If you need a server for MatchMaking and one for TURN, you should have two instances of `DiarkisInterface`.

**Usage Example:**

```csharp
  class Program
  {
      static void Main(string[] args)
      {
          var eventHandler = new DiarkisEventHandler(); // Event Handler object (cf: Events)
          var logSeverity = DiarkisLoggerSeverity.Error;
          var logAction = new Action<string>((str) => {Console.WriteLine(str); });
          var loggerFactory = new Diarkis.DiarkisLoggerFactory(logSeverity, logAction); // Logger Factory Object (cf: Logging)

          // DiarkisInterface object is created here (The ServerType is passed as parameter of the constructor UDP/TCP)
          Diarkis.DiarkisInterface diarkis = new Diarkis.DiarkisInterface(loggerFactory, ServerType.UDP, eventHandler);
          diarkis.HttpHost = "192.168.100.12:7000";

          // StartRuntimeThread will initiate the update loop using multiThreading,
          // Since Unity is not a thread safe Engine, it is not recommended to use this function in Unity
          // The recommended behavior is to call diarkis.UpdateComponents(); inside the FixedUpdate function of the
          // DiarkisNetworkManager object
          diarkis.StartRuntimeThread();
          Console.WriteLine("Connecting to " + diarkis.HttpHost);

          // Send the Http Authentication get request to the Http Diarkis server, if the authentication is sucessful
          // the server will reply
          diarkis.sendHttpAuth();

          // note: DiarkisUtils.WaitFor() is using threads will block the main thread until the condition is met.
          // It is not recommended to use it in a Unity Project since it will make the game freeze.
          // Instead it is recommended to use the DiarkisAsync.WaitFor() function which is using the Unity Coroutine mechanism
          if (!DiarkisUtils.WaitFor(() => { return diarkis.IsConnected(); }))
          {
              Console.WriteLine("Connection Timeout");
              return;
          }
          Console.WriteLine("UDP Connection success");

          // listen to the Room Join event (just an example)
          eventHandler.RegisterCallback(Diarkis.DiarkisEventType.RoomJoin,
          (DiarkisRoomJoinEventArgs eventArgs) => { Console.WriteLine("Room Joined!"); });

          // Join a random room
          diarkis.Room.SendJoinRandomRoom(4, 60, 100, true);

          // do any required more actions ...
          return;
      }
  }
```

#### [UDP](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Modules/DiarkisUDP.cs)

This module is used to create and manage a `UDP` connection with a Diarkis server; several other modules, such as Room and P2P, rely on it.

#### [TCP](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Modules/DiarkisTCP.cs)

This module manages and creates a `TCP` connection with a Diarkis server. Other modules like Room and P2P can be configured to use either `UDP` or `TCP`, though some modules are dependent only on `UDP`.

#### [Room](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Modules/DiarkisRoom.cs)

This module allows multiple clients to join a `Room` and exchange data, messages, or object information. A `P2P` connection can be initiated with group members under the condition that the `Room` is using a `UDP` connection. You can only join one `Room` at a time, and to enter the same `Room`, it must be connected to the same server.

#### [P2P](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Modules/DiarkiP2P.cs)

This module is used to create and manage a direct peer-to-peer connection between two clients. It is used as an optional feature within the `Room` module. Clients can initiate `P2P` synchronization and transmit data without using an intermediate server after having joined a `Room`.

#### [Group](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Modules/DiarkisRoom.cs)

The `Group` module allows multiple clients to join a group and exchange messages. The number of Groups one can join at the same time is unlimited, and it doesn't require being connected to the same server to join the same Group.

#### [Field](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Modules/DiarkisField.cs)

This module looks similar to the `Room` but varies in many ways. Only one `Field` exists within a server network. With Diarkis server logic, multiple `UDP` servers can be configured as part of the same mesh network. A `Field` is divided into several `Grids`, each assigned to a server. Each server is responsible for conveying client information within its `Grid`. This module is well-suited for large environments where a high number of players might connect simultaneously.

#### [Direct Message](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Modules/DirectMessage.cs)

This `Direct Message` (DM) module can be used to send unicast messages directly to members on separate servers. Unlike `Room` or `Group`, `DM` does not require joining the same room, and you can send directly if you know the `UserID`.

#### [MatchMaker](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Modules/DirectMatchMaker.cs)

The `MatchMaker` module contains functions and events for issuing matchmaking tickets. Ideally, matchmaking conditions are defined server-side. Clients simply set `TicketType` and issue a ticket using `IssueTicket()`. Once ticket issuance is completed (all players fulfilling matching conditions are found), a `TicketComplete` event is triggered, and players can communicate with other matched members using the `TicketBroadcast` command.

#### [Session](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Modules/DirectSession.cs)

`Session` is similar to the `Field` module in that it allows the same session to exist on different Diarkis servers within the same mesh network. However, it is not meant to share coordinate data but to exchange standard data for a limited group of players.

## Custom Commands

Most commands transmitted through the Diarkis module are `built-in commands`, meaning their content is known to the core library and parsed into specific types such as `DiarkisRoomJoinEventArgs`.

However, developers wishing to develop their own commands must add the command to both the server-side and client-side. To facilitate the creation and parsing of such commands, Diarkis provides a standalone binary called `Puffer`, available as linux or mac binaries in the `Diarkis Server Template` (a separate repository).

The json definition file containing some of the payloads and commands used in the sample is found at [CustomCommands.json](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/CustomCommands/json_definitions/CustomCommands.json).

Depending on how custom commands are defined server-side, parsing them is mostly done in `OnResponse` or `OnPush` events (in the cases of `UDP` or `TCP`). Here's an example of using a `Zoo` command defined as above:

```csharp
        public void OnResponse(DiarkisResponseEventArgs args)
        {
            if (args.GetVersion() == Zoo.VER && args.GetCommand() == Zoo.CMD)
            {
                Zoo zooCommand = new Zoo();
                if (!Zoo.Unpack(args.GetPayload().ToArray()))
                {
                    DiarkisNetworkManager.Instance.Logger.Error("Failed to parse Zoo command");
                    return;
                }
                long lion = zooCommand.Lion;
                byte[] penguins = zooCommand.Penguins;
            }
        }
```

## Using Multiple DiarkisInterface Instances

Although the DiarkisNetworkManager is designed to use a single connection to one Diarkis server, it's also possible to handle multiple connections simultaneously. For that reason, you can create multiple alternative DiarkisInterface objects via the DiarkisNetworkManager object, as shown in this example:

```csharp
        var diarkisLobby = DiarkisNetworkManager.GetDiarkisInterface("Lobby");
        var diarkisGame = DiarkisNetworkManager.GetDiarkisInterface("Game");
        diarkisLobby.EventHandler.RegisterCallback(DiarkisEventType.UDPConnect, new Action<DiarkisConnectionEventArgs>((args) => { Debug.Log("CONNECTED TO LOBBY SERVER."); }));
        diarkisLobby.EventHandler.RegisterCallback(DiarkisEventType.UDPConnect, new Action<DiarkisConnectionEventArgs>((args) => { Debug.Log("CONNECTED TO GAME SERVER."); }));

        DiarkisNetworkManager.Connect("Lobby", DiarkisTransportType.UDP, "LBY");
        DiarkisNetworkManager.Connect("Game", DiarkisTransportType.UDP, "GAME");
```

## Asynchronous Code

While events are the way to perform actions synchronously, developers may want certain scenarios to execute in a predefined order asynchronously. For that, there is a `WaitFor()` function defined in the [DiarkisUtils](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Core/Client/Utils/DiarkisUtils.cs) interface.

**Usage Example:**

```csharp
class Program
  {
      static void Main(string[] args)
      {
          Diarkis.DiarkisInterface diarkis = new Diarkis.DiarkisInterface(loggerFactory, ServerType.UDP, eventHandler);
          diarkis.HttpHost = "192.168.100.12:7000";
          diarkis.StartRuntimeThread();
          Console.WriteLine("Connecting to " + diarkis.HttpHost);
          diarkis.sendHttpAuth();
          if (!DiarkisUtils.WaitFor(() => { return diarkis.IsConnected(); }))
          {
              Console.WriteLine("Connection Timeout");
              return;
          }
          Console.WriteLine("UDP Connection success");
          Console.WriteLine("Joining a Room...");
          diarkis.Room.SendJoinRandomRoom(4, 60, 100, true);
          if (!DiarkisUtils.WaitFor(() => { return diarkis.Room.ID != ""; }))
          {
              Console.WriteLine("Room Join Timeout");
              return;
          }
          Console.WriteLine("Room Joined!");
          return;
      }
  }
```

Note: `DiarkisUtils.WaitFor()` uses the `Threading.Sleep()` function. It means that the main thread is blocking until the condition is met. Instead, it is recommended to use the `DiarkisAsync.WaitFor()` version available in the [DiarkisAsync](https://github.com/Diarkis/diarkis-help-center/blob/main/gitbook/renewal/en/diarkis-client/samples/unity/field-walker/Scripts/Plugin/Common/DiarkisAsync.cs) interface, which uses Unity's `Coroutine` mechanism instead of `Threads`.

**Unity Asynchronous Code Example:**

```csharp
void Start()
{
    StartCoroutine(ConnectAndJoinRoomAsync())
}

public IEnumerator ConnectAndJoinRoomAsync()
{
    DiarkisNetworkManager.Connect();
    DiarkisAsyncResult res = new DiarkisAsyncResult();
    yield return DiarkisAsync.WaitFor(() =>
    {
        return IsConnected();
    }, res);
    if (!res.completed)
    {
        if (Logger != null)
        {
            Logger.Error("Connection Time Out");
        }
        yield break;
    }

    Logger.Debug("Connection Success");
    Logger.Debug("Joining Random Room...");
    DiarkisNetworkManager.GetRoom().SendJoinRandomRoom(4, 60, 100, true);
    yield return DiarkisAsync.WaitFor(() =>
    {
        return DiarkisNetworkManager.GetRoom().ID != "";
    }, res);
    if (!res.completed)
    {
        if (Logger != null)
        {
            Logger.Error("Room Join Time Out");
        }
        yield break;
    }
    Logger.Debug("Room succesfully joined");
    yield return null;
}
```

### Catching Diarkis Events Asynchornously

Although Diarkis library is designed to call events through callback functions synchronously (as described in the [Events Section](#Events), it’s worth mentioning that combining the above function with event callbacks will allow catching event callbacks within an asynchronous context.

Here is an example of a function waiting asynchronously for a member to join using event callbacks:

```csharp
        void Start()
        {
            StartCoroutine(WaitForRoomMemberJoin())
        }

        IEnumerator WaitForRoomMemberJoin()
        {
            DiarkisAsyncResult res = new DiarkisAsyncResult();
            DiarkisPayloadEventArgs eventArgs = null;
            var callback = (Action<DiarkisPayloadEventArgs>)((args) => { eventArgs = args; });
            DiarkisNetworkManager.GetEventHandler()?.RegisterCallback(Diarkis.DiarkisEventType.RoomMemberJoin, callback, this);
            yield return DiarkisAsync.WaitFor(() =>
            {
                return eventArgs != null;
            }, res);

            DiarkisNetworkManager.GetEventHandler()?.UnregisterCallback(callback);
            if (res.completed)
            {
                // callback triggered
            }
            else
            {
                //callback trigger timeout
            }
            yield return null;
        }
```

## Custom Allocators

It's possible to arbitrarily set the allocator size to be used throughout the Diarkis Native Library code. For that, static functions `SetCustomAllocatorSize` and `SetCustomAllocator` are provided.

When feasible, this size should not exceed the available memory size, and an exception will be thrown if it does.

The following example sets the allocator size to 16MB. Diarkis libraries typically use no more than 500Kb, but it's recommended to use at least 4Mb.

**Usage Example:**

```csharp
  class Program
  {
      static void Main(string[] args)
      {
          //Parameters are the Size of the Buffer, and the alignment.
          ICustomAllocator _originalAllocator = DiarkisLib.SetCustomAllocatorSize(1024 * 1024 * 16, 16);

          // code using Diarkis ...

          // When Diarkis resources are done to be used and have been disposed, the Allocator can be safely reset
          DiarkisLib.SetCustomAllocator(_originalAllocator);
          return;
      }
  }
```

## Notes on Memory Safety

Diarkis `C#` SDK is based on the core Diarkis Library initially created in `C++` and compiled into native libraries. Automatically generated wrapper files in .cs allow `C++` native code usage in `C#`. However, `C++` and `C#` are not the same language, and the most significant difference is how they manage memory. `C#` relies on garbage collection (GC) for heap management, making it "memory-safe." `C++` has no GC, requiring developers to manage data allocation/deallocation.

Therefore, every wrapped class from the Native Diarkis Library is derived from the `IDisposable` type in `C#`. These objects have the function to instruct the `Garbage Collector` not to care about the data, allowing developers to release unmanaged resources using the `Dispose()` function as desired.

It's essential to understand that once the `Dispose()` function is called, any code dependent on the unmanaged resources allocated to this object may cause a `Memory Exception`, `Unity Editor` crashes, or `Memory Leaks`. If such issues arise, releasing a resource too early or using one too late might have been an issue.

## Building on iOS

When building for iOS, it's important to set some specific values in the `Player Settings`. Set `Managed Stripping Level` to `minimal` in the `Optimization` section.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-01d72d8153ea788a6979d3a15c91ad4ebbd1004d%2Fmanaged-code-stripping-level.png?alt=media)

When building for iOS, it may be necessary to perform some minor adjustments so that Diarkis Libraries can run correctly. After pressing the `Build Button` in Unity Editor, Unity will generate the `xcode project folder`. Open the xcode project, select the `Unity-iPhone` target, and open the `General` tab. Next, you need to add two of the runtime Diarkis library files to the project in the left panel, available in the `Libraries\Diarkis\Libraries\iOS` folder. Then, add these files to the `Frameworks, Libraries, and Embedded Content` list. This is necessary to ensure that the libraries will be copied to your iOS device when installing the app.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-42192d0452993471f8efc25b06b39c3d25ff5c22%2Fios-build.png?alt=media)

## Building on visionOS and visionOS-Simulator

Building for visionOS is similar to iOS, but there are some additional steps required in xcode. The first thing to note is that you can switch between visionOS and visionOS-Simulator as the platform in Unity's Build Window.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-21ae40f816536ce835608926012c1efdd5846d87%2FvisionOS-build.png?alt=media)

Moreover, depending on whether you are building for the simulator or an actual visionOS device, you'll need to change library parameters within the editor. For instance, if you want to build for `VisionOS-Simulator-arm64`, you need to select two libraries in the `Packages>Diarkis Plugin Sample>Core>Libraries>visionOS-Simulator-arm64` folder and set the platform to `visionOS`, disabling conflicting libraries.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-2aaf343c304d1bbc42dd1a3cd05b7aaab31817f8%2FvisionOS-library.png?alt=media)

Once the build is complete, open the xcode project file in xcode (version 15.2 or higher is required to support visionOS). Then, similarly to iOS builds, add the corresponding library for the target platform to your project in the left panel of xcode.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-7db810d940122ab8eeba5a4a2c0bbbf65fc58fc4%2FvisionOS-addlib.png?alt=media)

Be sure to check `Add to target`: Unity-visionOS\`

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-8309c346b370f6198d23907ca08918bea12d7cd2%2FvisionOS-libfolder.png?alt=media)

Next, in `Unity-VisionOS > General > Frameworks, Libraries, and Embedded Content`, set the two Diarkis libraries to `Embed & Sign`.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-3a0018b5b22584d2e0b48f23cdd716df977b6b60%2FvisionOS-embedlib.png?alt=media)

(This step is specific to simulators).\
In `Unity-VisionsOS > Build Settings > Linking - General`, add the value `-ld64` to `Other Linker Flags`.

With this linker correctly set, your app is ready to build for visionOS.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-f2564a1c0da91dd65407f5535048b7e3316b3af4%2FvisionOS-simulator.png?alt=media)

## Obfuscation

Obfuscation tools can be used safely with Diarkis. For example, [Beebyte Obfuscator from the Unity Asset Store](https://assetstore.unity.com/packages/tools/utilities/obfuscator-48919) has been used to build the obfuscated version of the Diarkis sample. The binary file contains assemblies to hide the application's logic, making it difficult for hackers to reverse-engineer the source code.

To use Beebyte Obfuscator, you must first purchase a license, download it from the `Window > Package Manager` window, and import it into the project.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-80bcd0e18dee9e91a21249a9ae028a5afcbc20ec%2FObfuscatorPackager.png?alt=media)

When the package is imported, a `settings prefab` is created in `Assets/Editor/Beebyte/Obfuscator/ObfuscsatorOptions`. By altering these settings, you can opt for stronger or lighter obfuscation, though the default settings should work well.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-d62f78f4fdd4bc94f4c8748f1a91b4d33d725802%2FObfuscatorInspector.png?alt=media)

You can then build the project from the `File > Build Settings` window, ensuring to use the `Clean Build` option to ensure obfuscation settings are applied between builds.

![DiarkisNetworkManager Inspector UI](https://3799879693-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FryZ6XqKeHRZxcxMovWdn%2Fuploads%2Fgit-blob-43c67f46d772917b01bb9937d79c7cfb5f905615%2FBuildButton.png?alt=media)
