# イベント処理の注意点

## 概要

UnrealEngine の Diarkis Plugin Sample には、サーバからの Response 通知 / Push 通知 のコールバックを受け取る仕組みとして、以下の３種類の仕組みを用意しております。

1. `DiarkisDispatch` クラスを利用した仕組み
2. `EventHandler` クラスを利用した仕組み
3. `DiarkisSyncData` クラスを利用した仕組み

こちらのコールバックイベントの受け取る仕組みはサンプルのコードになりますので、もし自前の仕組みを使用される場合は置き換えて頂くことが可能です。

## DiarkisDispatch クラスを利用した仕組み

### 概要

* `DiarkisDispatch` クラスは、Diarkis Plugin Sample に用意されたサーバからの Response 通知 / Push 通知 のコールバックを受け取る仕組みの一つです。
* サーバから通知されたコールバックは、`DiarkisXXXXDelegate` の `DiarkisDispatch` にキューイングされます。
* キューイングされた `DiarkisDispatch` は、`UDiarkisNetworkManager::Tick()` から呼び出される `InGameDiarkisInterface::Execute()`で実行されています。
* キューイングされたイベントは、Tick() の呼び出し間隔で処理されますのでご注意ください。もし、タイムラグなく処理されたい場合は、必要に応じて `InGameDiarkisInterface::Execute()` を呼び出す場所を調整ください。
* 現状 `DiarkisDispatch` クラスの仕組みと `EventHandler` クラスを利用した仕組みと混在していますが、今後は `DiarkisDispatch`の仕組みが、`DiarkisPlugin` の Sampleとしてアプリにコールバックイベントを返すメインの仕組みになる予定です。

### 処理シーケンス

ここでは、UDP サーバの Connect コマンドの処理の流れで説明しますが、他のモジュール（Room, P2P, MatchMakerなど）のコマンドのコールバックイベントも流れは一緒になります。それぞれの処理に合わせてクラスや関数を置き換えてご確認ください。

例えば UDP/TCP サーバ接続のコールバックイベントを受ける際の流れは以下になります。

まずは、サーバ からの Response 通知 / Push 通知 のコールバックを `DiarkisDispatch` でキューイングします。

1. アプリから UDP/TCP サーバに Connect します。
2. UDP/TCP サーバからの Response や Push 通知は、`DiarkisUdpBase` クラスで `udp_->GetConnectedEvent()` コールバックイベントにセットされている `DiarkisUdpBase::OnConnect()` が呼び出されます
3. `DiarkisUdpBase` の 子クラス `InGameDiarkisUdp::OnConnect()` が呼び出されます。
4. `InGameDiarkisUdp::OnConnect()` 関数内の `Dispatch()` でイベントをキューイングします。

{% @mermaid/diagram content="sequenceDiagram
actor app
participant gam as InGameDiarkisUdp
participant udp as DiarkisUdpBase
participant lib as libDiarkis
participant ser as UDP server

box client
participant app
participant gam
participant udp
participant lib
end

app ->> udp: 1. DiarkisUdpBase::Connect()
udp ->> lib: IDiarkisUdp::Connect()
lib ->> ser: Request
ser ->> lib: Response
lib ->> udp: 2. udp\_->GetConnectedEvent()
udp ->> gam: 3. InGameDiarkisUdp::OnConnect()" %}

```c++
void InGameDiarkisUdp::OnConnect(const DiarkisConnectionEventArgs& e)
{
    DiarkisUdpBase::OnConnect(e);
    
    ....
    ....

    Dispatch(args, [this](std::shared_ptr<DiarkisDispatch::Args> args)
    {
        delegate_->OnConnect(*this, *std::static_pointer_cast<IDiarkisUdpDelegate::ConnectArgs>(args));
    });
}
```

次に、ゲームのスレッドから `DiarkisDispatch` でキューイングされたイベントを `Execute()` で実行します。

1. ゲームのスレッドの `UDiarkisNetworkManager::Tick()` から `InGameDiarkisInterface::Execute()` で Delegate が処理されます。
2. `InGameDiarkisUdp::OnConnect()` で `Dispatch()` された `delegate_->OnConnect()` が呼び出されます。
3. `DiarkisSampleUdpDelegate::OnConnect()` が呼び出されます。

{% @mermaid/diagram content="sequenceDiagram
actor app
participant del as DiarkisSampleUdpDelegate
participant udp as InGameDiarkisUdp
participant int as InGameDiarkisInterface
participant Net as UDiarkisNetworkManager::Tick

box client
participant app
participant del
participant udp
participant int
participant Net
end

Net ->> int: 1. DiarkisLists\_\[serverType]->Execute()
int ->> udp: 1. InGameDiarkisUdp->Execute()
udp ->> del: 2. delegate\_->OnConnect()
del ->> app: 3. DiarkisSampleUdpDelegate::OnConnect()" %}

### DiarkisDispatch の関連クラス

* 役割の概要
  * アプリレイヤーで Diarkis コールバックイベントを受け取るためのクラス群（新）
* コードの場所
  * DiarkisPluginSample/Source/DiarkisExtension/XXXXX/Delegate
* 各クラス
  * `DiarkisDispatch.h / DiarkisDispatch.cpp` : Diarkis のコールバックイベントをキューイングや実行するクラス
  * `DiarkisUDPDelegate.h` : Diarkis の Group のコールバックイベントをキューに入れるクラス
  * `DiarkisP2PDelegate.h` : Diarkisの P2P のコールバックイベントをキューに入れるクラス
  * `DiarkisMatchMakerDelegate.h` : Diarkis の MatchMaker のコールバックイベントをキューに入れるクラス
  * `DiarkisRoomDelegate.h` : Diarkis の Room のコールバックイベントをキューに入れるクラス
  * `DiarkisSessionDelegate.h` : Diarkis の Session のコールバックイベントをキューに入れるクラス
  * `DiarkisGroupDelegate.h` : Diarkis の Group のコールバックイベントをキューに入れるクラス

## EventHandler クラスを利用した仕組み

### 概要

* `EventHandler` クラスは、Diarkis Plugin Sample に用意されたサーバからの Response 通知 / Push 通知 のコールバックを受け取る仕組みの一つで、BluePrint用 コールバックイベントを返すための仕組みとして用意されています。
* サーバから通知されたコールバックは、`DiarkisNetworkXXXXEventEmitter` の `UDiarkisNetworkEventHandler` にキューイングされます。
* キューイングされた `UDiarkisNetworkEventHandler` は、`UDiarkisNetworkManager::Tick()` から呼び出される `IUDiarkisNetworkEventHandler::Update()` で実行されています。
* キューイングされたイベントは、Tick() の呼び出し間隔で処理されますのでご注意ください。もし、タイムラグなく処理されたい場合は、必要に応じて `UDiarkisNetworkEventHandler::Update()` を呼び出す場所を調整ください。
* 現状 `DiarkisDispatch` クラスの仕組みと `EventHandler` クラスを利用した仕組みと混在していますが、今後は `DiarkisDispatch`の仕組みが、`DiarkisPlugin` の Sampleとしてアプリにコールバックイベントを返すメインの仕組みになる予定です。

### 処理シーケンス

ここでは、UDP サーバの Connect コマンドの処理の流れで説明しますが、他のモジュール（Room, P2P, MatchMakerなど）のコマンドのコールバックイベントも流れは一緒になります。それぞれの処理に合わせてクラスや関数を置き換えてご確認ください。

例えば UDP/TCP サーバ接続のコールバックイベントを受ける際の流れは以下になります。

まずは、サーバ からの Response 通知 / Push 通知 のコールバックを `EventHandler` でキューイングします。

1. アプリから UDP/TCP サーバに Connect します。
2. UDP/TCP サーバからの Response や Push 通知は、`udp_->GetConnectedEvent()` コールバックイベントにセットされている `DiarkisUdpBase::OnConnect()` が呼び出されます。
3. `DiarkisUdpBase OnConnect()` が呼び出され、内部的に `udp_->IsConnected() == true` に変更されます。
4. `UDiarkisNetworkManager::Tick()` から `UpdateConnected()` が定期的に呼び出され、`GetUdpBase()->IsConnected()==true` に切り替わった時に、`EnqueueOnNetworkConnect()` が呼び出されます。
5. `UDiarkisNetworkCoreEventEmitter::EnqueueOnNetworkConnect()` で `OnNetworkConnect` がキューイングされます。

{% @mermaid/diagram content="sequenceDiagram
actor app
participant udp as DiarkisUdpBase
participant lib as libDiarkis
participant ser as UDP server

box client
participant app
participant udp
participant lib
end

app ->> udp: 1. DiarkisUdpBase::Connect()
udp ->> lib: IDiarkisUdp::Connect()
lib ->> ser: Request
ser ->> lib: Response
lib ->> udp: 2. DiarkisUdpBase OnConnect()" %}

次に、ゲームのスレッドから `UDiarkisNetworkEventHandler` でキューイングされたイベントを `Update()` で実行します。

1. ゲームのスレッドの `UDiarkisNetworkManager::Tick()` から `EventHandler->Update()` が呼び出されます。
2. `UDiarkisNetworkEventHandler::Update()` で、キューイングされたイベントが `Event->CallFunction()` で呼び出されます。
3. `IDiarkisNetworkCoreEvent` の派生クラスの `ADiarkisSampleBase` の子クラスの `BPDiarkisPluginSample::OnNetworkConnect()` のイベントが呼び出されます。
4. `BPDiarkisPluginSample` の親クラスの `ADiarkisSampleBase::OnNetworkConnect_Implementation()`が呼び出されます。

{% @mermaid/diagram content="sequenceDiagram
actor app
participant del as ADiarkisSampleBase
participant plg as BPDiarkisPluginSample
participant han as UDiarkisNetworkEventHandler
participant Net as UDiarkisNetworkManager::Tick

box client
participant app
participant del
participant plg
participant han
participant Net
end

Net ->> han: 1. EventHandler->Update();
han ->> plg: 2. Event->CallFunction(Instance);
plg ->> del: 3. BPDiarkisPluginSample::OnNetworkConnect()
del ->> app: 4. ADiarkisSampleBase::OnNetworkConnect\_Implementation()" %}

### 関連クラス

* 役割の概要
  * BluePrint で Diarkis コールバックイベントを受け取るためのクラス群（旧）
* コードの場所
  * DiarkisPluginSample/Source/DiarkisExtension/XXXXX/Events
* 各クラス
  * `UDiarkisNetworkEventHandler.h` / `UDiarkisNetworkEventHandler.cpp` : Diarkis のコールバックイベントをキューイングや実行するクラス
  * `Interfaces` ディレクトリ（Diarkis Plugin のコールバックを受け取るインターフェースクラス）
    * `UDiarkisNetworkCoreEvent.h` : Diarkis Plugin の Core 機能のコールバックを受け取るインターフェースクラス
    * `UDiarkisNetworkRoomEvent.h` : Diarkis Plugin の Room 機能のコールバックを受け取るインターフェースクラス
    * `UDiarkisNetworkGroupEvent.h` : Diarkis Plugin の Group 機能のコールバックを受け取るインターフェースクラス
    * `UDiarkisNetworkFieldEvent.h` : Diarkis Pluginの Field 機能のコールバックを受け取るインターフェースクラス
    * `UDiarkisNetworkP2PEvent.h` : Diarkis Plugin の P2P 機能のコールバックを受け取るインターフェースクラス
    * `UDiarkisNetworkMatchMakerEvent.h` : Diarkis Plugin の MatchMaker 機能のコールバックを受け取るインターフェースクラス
  * `Emitters` ディレクトリ（Diarkis イベントをキューイングするクラス）
    * `UDiarkisNetworkEventEmitterBase.h / UDiarkisNetworkEventEmitterBase.cpp` : 様々なイベントを生成するためのベースクラス
    * `UDiarkisNetworkCoreEventEmitter.h / UDiarkisNetworkCoreEventEmitter.cpp` : Diarkis Core イベントをキューイング用クラス
    * `UDiarkisNetworkRoomEventEmitter.h / UDiarkisNetworkRoomEventEmitter.cpp` : Diarkis Room イベントをキューイング用クラス
    * `UDiarkisNetworkGroupEventEmitter.h / UDiarkisNetworkGroupEventEmitter.cpp` : Diarkis Group イベントのキューイング用クラス
    * `UDiarkisNetworkFieldEventEmitter.h / UDiarkisNetworkFieldEventEmitter.cpp` : Diarkis Field イベントのキューイング用クラス
    * `UDiarkisNetworkP2PEventEmitter.h / UDiarkisNetworkP2PEventEmitter.cpp` : Diarkis P2P イベントのキューイング用クラス
    * `UDiarkisNetworkMatchMakerEventEmitter.h / UDiarkisNetworkMatchMakerEventEmitter.cpp` : Diarkis MatchMaker イベントのキューイング用クラス

## DiarkisSyncData クラスを利用した仕組み

### 概要

* `DiarkisSyncData` クラスは、Diarkis Plugin Sample に用意されたサーバからの Response 通知 / Push 通知 のコールバックを受け取る仕組みの一つで、キャラクターの位置同期など遅延を抑えたいコールバックイベントを処理する仕組みとして用意されています。

まずは、Room のリレー通信、P2P通信で取得した Payload をキューイングします。

1. `DiarkisRoom::OnRoomMemberBroadcast()` が呼び出されます。
2. `syncData_->OnPositionSync()` が呼び出ばれます。
3. `payloadSyncQueue.push()` で Payload をキューイングします。

次に、キューイングし Payload をデキューします。

1. `UDiarkisSyncComponent::TickComponent()` の処理で、 `DiarkisRemoteMovementSync::UpdateMovement()` が呼び出されます。
2. `DequeueLastFrame()` で Payload をデキューします。
