このページは編集中です。更新が保留になっている可能性があります。
server | v5 switch to v4  

新機能

目次

新しい個別の設定ファイル

プラグインは、自身のファイル上で個別に設定されるようになりました。 ファイルは、以前に使用された設定ファイルと同じフォルダーにある「plugin.config」です。 ただし、構成する構文は同じです。

トップに戻る

新しいロギングインターフェース

プラグインからアクセスできるロギングインターフェースを追加しました。

以前の方法

v4では、IPluginHostロギングメソッドを直接呼び出していました。

private IPluginHost pluginHost;

public bool SetupInstance(IPluginHost host, Dictionary<string, string> config, out string errorMsg)
{
    pluginHost = host;
}

///...

this.pluginHost.LogDebug("debug");
this.pluginHost.LogWarning("warning");
this.pluginHost.LogError("error");
this.pluginHost.LogFatal("fatal");

トップに戻る

新しい方法

IPluginHostロギングメソッドを呼び出すのではなく、プラグインインタンスごとに新しいIPluginLoggerオブジェクトを作成する必要があります。 このオブジェクトを利用して、プラグインからすべてをログします。

public const string PluginName = "MyPlugin";

private IPluginLogger pluginLogger;

public override bool SetupInstance(IPluginHost host, Dictionary<string, string> config, out string errorMsg)
{
    pluginLogger = host.CreateLogger(PluginName);
    // ...
}

// ...

this.pluginLogger.LogDebug("debug");
this.pluginLogger.LogWarning("warning");
this.pluginLogger.LogError("error");
this.pluginLogger.LogFatal("fatal");

ロガー(IPluginHost.CreateLogger(loggerName)に渡されます)の名前を設定する際、ロガー名にはPlugin.を付け加えます。このためMyPlugin.MyClassを設定すると、これはPlugin.MyPlugin.MyClassとしてログされます。 たとえばログレベルが最大レベルに設定された場合に、上記のコードスニペットはこれらのログエントリーを生成します。

2020-01-31 17:10:07,394 [1] DEBUG  Plugin.MyPLugin - debug
2020-01-31 17:10:07,901 [1] WARN  Plugin.MyPLugin - warning
2020-01-31 17:10:08,152 [1] ERROR  Plugin.MyPLugin - error
2020-01-31 17:10:08,724 [1] FATAL  Plugin.MyPLugin - fatal

トップに戻る

プラグインHook処理の向上

ICallInfoはプラグインhookメソッド内で取得する引数で、メソッド呼び出しのコンテキストを表します。 このコンテキストオブジェクトは、ルーム内での通常のワークフローを保証するhook呼び出しが発生した後に制限時間内に処理される必要があります。

トップに戻る

匿名関数

匿名関数(ラムダ表現または匿名メソッド)をHTTPリクエストのコールバックとして使用していた場合(以下の例を参照ください)には、今後も使用し続けることができます。

匿名メソッドとしてのHTTPコールバックの例:

private void SendRequest(ICallInfo callInfo)
{
    HttpRequest request = new HttpRequest
    {
        Callback = delegate
                   {
                       ProcessCallIfNeeded(callInfo);
                   },

ラムダ表現としてのHTTPコールバックの例:

private void SendRequest(ICallInfo callInfo)
{
    HttpRequest request = new HttpRequest()
    {
        Callback = (response, userObject) => ProcessCallIfNeeded(callInfo),

以前のHTTPメソッドコールの置換を推奨します:

PluginHost.HttpRequest(request);

上記は、2つの引数をともなう新しい負荷メソッドに置換してください:

PluginHost.HttpRequest(request, callInfo);

トップに戻る

Ld Way 以前の方法

これまでは、HTTPレスポンスコールバック内のICallInfoオブジェクトを取得するには回避策を講じなければなりませんでした。 カスタムかつ任意のHttpRequest.UserStateを使用し、ICallInfoオブジェクトを格納していました。

例:

private void CallbackOldLogic(IHttpResponse response, object userObject)
{
    ICallInfo callInfo = userObject as ICallInfo;
    ProcessCallIfNeeded(callInfo);
}

private void SendRequest(string url, ICallInfo callInfo)
{
    HttpRequest request = new HttpRequest
    {
        Url       = url,
        Callback  = CallbackOldLogic,
        UserState = callInfo
    }
    this.PluginHost.HttpRequest(request);

トップに戻る

新しい方法

今後は、新しいPluginHost.HttpRequest負荷メソッド内のプラグインhookコンテキスト(ICallInfo)を渡します。 その後、IHttpResponseからそれを取得します。

例:

private void CallbackNewLogic(IHttpResponse response, object userObject)
{
    ICallInfo callInfo = response.CallInfo;
    ProcessCall(callInfo);
}

private void SendRequest(string url, ICallInfo callInfo, object userObject = null)
{
    HttpRequest request = new HttpRequest
    {
        Url       = url,
        Callback  = CallbackNewLogic,
        UserState = userObject,
        CallInfo  = callInfo
    };
    this.PluginHost.HttpRequest(request, callInfo);

トップに戻る

新しい非同期の挙動

以前の方法

v4では、プラグインhookの処理を遅延させるには非同期HTTPリクエストまたはタイマー向けのICallInfo.Deferを呼び出す必要がありました。

HTTPリクエストの例:

private void SendRequest(string url, ICallInfo callInfo)
{
    HttpRequest request = new HttpRequest
    {
        Url       = url,
        Async     = true,
        Callback  = delegate { ProcessCallIfNeeded(callInfo); },
    };
    this.PluginHost.HttpRequest(request);
    callInfo.Defer();
}

タイマーの例:

private void DelayLogic(ICallInfo callInfo, Action logic, int delayMs)
{
    PluginHost.CreateOneTimeTimer(
                () =>
                {
                    logic();
                    ProcessCallIfNeeded(callInfo);
                },
                delayMs);
    callInfo.Defer();
}

トップに戻る

新しい方法

ICallInfo.Defer は削除され、その代わり、以下の場合にhookコンテキストの呼び出しが内部的に自動で延期されます:

  • httpRequest.Async = trueHttpRequestを送信している場合
  • タイマーを作成している場合

HTTPリクエストの例:

private void SendRequest(string url, ICallInfo callInfo)
{
    HttpRequest request = new HttpRequest
    {
        Url       = url,
        Async     = true,
        Callback  = delegate { ProcessCallIfNeeded(callInfo); },
        CallInfo  = callInfo
    };
    this.PluginHost.HttpRequest(callInfo, request);
}

タイマーの例:

private void DelayLogic(ICallInfo callInfo, Action logic, int delayMs)
{
    PluginHost.CreateOneTimeTimer(
                callInfo,
                () =>
                {
                    logic();
                    ProcessCallIfNeeded(callInfo);
                },
                delayMs);
}

トップに戻る

ファイバーアクセス

ファイバーは、FIFO方式で1つずつ順番に実行されるタスクのリストです。 1つのスレッドで実行されることを意味するわけではありません。 実際には、複数のスレッドで実行されますが、1つずつ実行されます。 したがって、最初のタスクはスレッドAで実行され、終了すると、2番目のタスクはスレッドBで実行されます。 ただし、どんな時も、1つのスレッドだけがルームデータにアクセスします。 多くのファイバーが同じデータにアクセスしようとする場合、ロックを使用します。

プラグインからルームファイバーを取得するには:

IPluginFiber fiber = this.PluginHost.GetRoomFiber();

トップに戻る

キューへの追加

以下を使用して、ルームのファイバーへのアクションをキューに入れることができます:

PluginHost.Enqueue(someAction);

または、上記で取得したファイバーを使用できます。

int r = fiber.Enqueue(someAction);
if (r == 0)
{
   // success
}
else
{
   // error
}

トップに戻る

タイマー

IPluginFiberIPluginHostと同じメソッドを共有しますが、 ICallInfo を必要とせず、hookコンテキスト外でスレッドセーフで実行できる点が異なります。

object timer = fiber.CreateOneTimeTimer(someAction, executeAfterMs);
\\ ...
fiber.StopTimer(timer); // in case you want to abort before delay is expired and someAction is executed
object timer = fiber.CreateTimer(someAction, firstExecutionAfterMs, repeatEachMs);
fiber.StopTimer(timer);

トップに戻る

IFactoryHost

ルーム外でのロックのない処理も、新たにサポートされるようになりました。これは、アプリケーション全体へのサービスに使用できます(すなわち、チート対策サービス、ブロードキャスティングなど)。この処理は、IPluginFiberメカニズムを使用して完全に構築されています。 プラグインファイバーはルームファイバーに類似したファイバーですが、ルーム外で作動します。 プラグインファイバーには任意の場所からキューに追加でき、操作はサーバー時間にもとづいて実行されます。 IPluginFiberを取得するには、IFactoryPlugin2から提供されるIFactoryHostのインスタンスが必要です。 IFactoryPlugin2は標準のIPluginFactoryを1つのメソッドで拡張したインターフェースです:

void SetFactoryHost(IFactoryHost factoryHost, FactoryParams factoryParams);

このメソッドは、プラグインのライフタイム中に1回、プラグインファクトリがインスタンス化されIFactoryHostインスタンスを提供した直後に呼び出されます。IFactoryHostインスタンスは プラグインファイバーとプラグインロガーを提供します。

IPluginFiber CreateFiber();

IPluginLogger CreateLogger(string loggerName);

FactoryHostによって作成されたファイバーは、ルーム外(すなわち、新しいルームの作成時)でも、キューに追加するルーム内でも使用できます。 または、ルームコンテキスト外でタイマー操作にも使用できます。

トップに戻る

新しい同期の挙動

「同期HTTPリクエスト」(httpRequest.Async = falseとともにHttpRequestを送信)を対象に、レスポンスまたはタイムアウトを取得するまでルームファイバー(すなわち、ルームメッセージは処理されません)を停止します。

以前のIPluginHost.HttpRequestメソッドによるブロック中:HTTPレスポンスが受信されるかタイムアウトするまでは返しません。 このアプローチのおもな問題点は、スレッドがブロックされ、コールバック実行がこのスレッドのキューにプッシュされるということです。 スレッドがブロックされているため、このコールバックは実行されません。 結果として、タイムアウトを取得します。 新しいアプローチとの主な相違点は、新しいIPluginHost.HttpRequestメソッドの性質上、ブロックしないという点です。 このメソッドはブロックしません。 つまり、ユーザーコードをリライトする必要があります。コールが作成されたプラグインhookと、使用されたHTTPリクエストの両方をアップデートする必要があります。 プラグインhookは、HTTPキューにリクエストをプッシュした直後に新しいIPluginHost.HttpRequestを返す点を認識する必要があります。 コールバック内で、まだ完了していない場合にはICallInfoオブジェクトを処理する必要があります(続行または操作を中断するには、 callInfo.ContinueFailまたはCancelを 呼び出します。今後は、スレッドの代わりにルームファイバーをブロックします。 リクエストへのレスポンスを取得するか、タイムアウトするまでは、新たなタスクは処理されません。

トップに戻る

新しいキックの理由

新しい RemoveActorReason.GlobalBanned(2)を渡すと、削除されたユーザーは、認証トークンが期限切れになりユーザーが再度認証されるまで、ルームに参加できなくなります。 その後、カスタム認証でユーザーを拒否できます。

トップに戻る

AuthCookieの更新

このメソッドを使用して、アクターごとに安全な認証Cookieを更新できるようになりました。

void IActor.UpdateSecure(string key, object value)

トップに戻る

すべてのキャッシュ操作への対応

これで、すべてのキャッシュ操作を実行できます。 クライアントへのイベント送信を伴わないすべてのキャッシュ操作では、新しいメソッドを使用します。

bool IPluginHost.ExecuteCacheOperation(CacheOp operation, out string errorMsg)

トップに戻る

より柔軟で強力なHTTPリクエストAPI

  • PUTメソッドへの対応が追加されました。
  • HttpRequet.ClientCertificateを使用してカスタム証明書を渡すことができます。
  • HttpRequestプロパティ(Accept, ContentType)を使用して、いくつかの制限されたHTTPリクエストヘッダーを設定できます。
  • `IHttpResponse.Headersを使用してHTTPレスポンスヘッダーを取得できます。

ドキュメントのトップへ戻る