# RFC (Remote Function Call)

Для упрощения работы с RPC, результат которых необходимо получить на вызвавшей их стороне (например, при выполнении какого-то действия, доступного только на сервере) библиотека предоставляет обёртку механизма RPC самой библиотеки, называемую RFC (Remote Function Call). Обёртка состоит из двух компонентов: компонент вызова и обработчик.

Реализованная обёртка позволяет выполнять RFC, идентифицируемые сразу по 3 атрибутам: название модификации (пространство имён), название функции в модификации, типы аргументов функции. Таким образом, обёртка поддерживает перегрузку функций (т.е. создание двух функций с одинаковыми названиями, но разными аргументами).

Компонент вызова - это объект, который создаётся на вызывающей функцию стороне, и используется для строго типизированного вызова функции и получения [Promise](https://workshop-guide.magicbyte.ru/mbsl-docs/modeli-vyzova-funkcii/promise-obeshanie-znacheniya) результата выполнения удалённой функции. В библиотеке этот компонент представлен семейством классов MBSL\_RFC. При использовании компонента на клиенте параметр recipient можно игнорировать. При использовании на сервере он указывает получателя RFC (NULL = недопустимое значение; обёртка не поддерживает одновременный вызов удалённой функции у каждого игрока).

```clike
//N - число аргументов (от 0 до 7)
class MBSL_RFCN<Class ReturnType, Class Arg1, ..., Class ArgN> : Managed
{
    //Конструктор. Требует передать название модификации (пространство имён)
    //А также название функции в этой модификации (пространстве имён).
    void MBSL_RFCN(string modname, string functionname);
    //Вызвать удалённую функцию с указанными аргументами и получить Promise результата
    MBSL_Promise<ReturnType> Invoke(Arg1 arg1, ..., ArgN argN, PlayerIdentity recipient = NULL);
}

​//N - число аргументов (от 0 до 7)
//Вариант, возвращающий PromiseRef
class MBSL_RFCNRef<Class ReturnType, Class Arg1, ..., Class ArgN> : Managed
{
    //Конструктор. Требует передать название модификации (пространство имён)
    //А также название функции в этой модификации (пространстве имён).
    void MBSL_RFCNRef(string modname, string functionname);
    //Вызвать удалённую функцию с указанными аргументами и получить Promise результата
    MBSL_PromiseRef<ReturnType> Invoke(Arg1 arg1, ..., ArgN argN, PlayerIdentity recipient = NULL);
}

//Вариант без аргументов
class MBSL_RFC0<Class ReturnType> : Managed
{
    //Конструктор. Требует передать название модификации (пространство имён)
    //А также название функции в этой модификации (пространстве имён).
    void MBSL_RFC0(string modname, string functionname);
    //Вызвать удалённую процедуру с указанными аргументами
    MBSL_Promise<ReturnType> Invoke(PlayerIdentity recipient = NULL);
}
```

Обработчик - это вызываемая [строго типизированная функция](https://workshop-guide.magicbyte.ru/mbsl-docs/modeli-vyzova-funkcii/strogo-tipizirovannye-funkcii) на другой стороне, которая получает аргументы, а также информацию о вызвавшем функцию игроке (если обработчик на сервере), и создаёт [Promise](https://workshop-guide.magicbyte.ru/mbsl-docs/modeli-vyzova-funkcii/promise-obeshanie-znacheniya) результата (даже если функция выполняется синхронно). В библиотеке этот компонент представлен семейством классов MBSL\_RFCHandler.

<pre class="language-clike"><code class="lang-clike">//N - число аргументов (от 0 до 7)
class MBSL_RFCHandlerN&#x3C;Class ReturnType, Class Arg1, ..., Class ArgN> : Managed
{
    //Добавить обработчик
    //Требует передать:
    //название модификации (пространство имён)
    //название функции в этой модификации (пространстве имён)
    //Функцию-обработчик
<strong>    static MBSL_RFCHandlerN Register(string modname, string funcname, MBSL_TypedFunction(N+1)&#x3C;MBSL_Promise&#x3C;ReturnType>, Arg1, ..., ArgN, PlayerIdentity> handler);
</strong><strong>    //Удаляет ранее добавленный обработчик.
</strong><strong>    //Возвращает false, если обработчик уже был ранее удалён.
</strong><strong>    bool Unregister();
</strong>}

//N - число аргументов (от 0 до 7)
//Вариант для функций, возвращающих PromiseRef.
class MBSL_RFCHandlerNRef&#x3C;Class ReturnType, Class Arg1, ..., Class ArgN> : Managed
{
    //Добавить обработчик
    //Требует передать:
    //название модификации (пространство имён)
    //название функции в этой модификации (пространстве имён)
    //Функцию-обработчик
    static MBSL_RFCHandlerN Register(string modname, string funcname, MBSL_TypedFunction(N+1)&#x3C;MBSL_PromiseRef&#x3C;ReturnType>, Arg1, ..., ArgN, PlayerIdentity> handler);
    //Удаляет ранее добавленный обработчик.
    //Возвращает false, если обработчик уже был ранее удалён.
    bool Unregister();
}
</code></pre>

При работе с удалёнными функциями (RFC) необходимо учитывать следующие особенности:

* При отключении клиента от игрового сервера (в том числе из-за выключения сервера) все удалённые вызовы, выполненные этим клиентом, но ещё не завершённые, будут автоматически отклонены на клиенте с ошибкой MBSL\_ConectionResetException. При этом сами удалённые функции на сервере никак не будут уведомлены об этом.
* При отключении клиента от игрового сервера (в том числе из-за выключения сервера) все удалённые вызовы, выполненные сервером к этому клиенту, но ещё не завершённый, будут автоматически отклонены на сервере с ошибкой MBSL\_ConectionResetException. При этом сами удалённые функции на клиенте никак не будут уведомлены об этом.
