JavaScriptゲームのカスタムプラグイン

Wargamingは現在、戦術カードゲームWoT:Generalsを開発しています。 Webバージョンは、LibCanvasとAtomJSを使用して、JSで記述されています。 私は開発に直接関与していましたが、私にとって興味深く、すべてのWebゲームで役立つ機能についてお話したいと思います。 つまり、Linuxパッケージマネージャーに触発され、次の機能を備えたゲームプラグインシステムについてです。

-プラグインの変更履歴
-ゲームのバージョンを更新する際のプラグインの自動更新
-ローカルホストでのプラグイン開発
-不安定なバージョンの場合など、無制限の数のブランチ
-依存関係(プラグインAはプラグインBを自動的にプラグインします)
-パックを作成する組み込み機能(前の段落の結果)
-ゲームクライアントの任意の部分の簡単な変更
-すべてのプラグインに対するゲームの作成者の完全な管理制御
-プラグインデータベースを検索する
-同時に、簡単なユーザーインストールとプラグインの便利な作業。

ゲーム


将軍は戦術的なカードゲームです。 多くの人がマジック:ザ・ギャザリングに精通していると思います。 主なゲームプレイは戦場5 * 3で、戦車、小隊、命令のカードで敵の本部を破壊します。



バトル画面に加えて、バトルに参加するデッキを選択するための「Hangar」、「Research Tree」、「Deck Editor」などの画面があります。



多くのアニメーションを持つオブジェクト(格納庫のカルーセル、研究ツリー、そしてもちろん戦闘)は、LibCanvasで記述され、html5キャンバスでレンダリングされます。 インターフェイスはhtmlで記述されたシンプルです。

プラグインシステムについて


プラグインは間違いなく便利な機能です。

まず、筋金入りのプレーヤーは、ゲーム体験を向上させるためにそれらを使用できます。
第二に、開発者自身がいくつかのアイデアを引き出すことができます。
第三に、一部のプラグイン作成者はすでにチームで働いています。
第四に、サードパーティの作者のおかげで、いくつかの脆弱性が正確に発見されました。

公式リリースはまだありませんが、プラグインシステムは1年半稼働しています。 私は彼らがどうあるべきかについて長い間考えていました。 そして、その結果として私たちがどのように、そして何に到達したかについての物語を以下で説明します。

もちろん、APIを書くことはできますが、プログラマーの想像力やサポートコストの増加といったアプローチの制限が気に入らなかったのです。 ゲームクライアントのあらゆる部分を変更できるようにしたかった。

幸いなことに、これは次の2つの理由で非常に簡単です。

-クライアントは非常に薄く、表示のみを処理します-すべてのロジックはサーバーに転送され、プラグインの影響を受けません
-すべての機密性の高い操作は、サードパーティのサーバーに転送されます-承認(パスワードが漏洩した可能性がある)および支払い(ユーザーがお金を失う可能性がある)。

その結果、安全に変更できるクリーンなゲームクライアントしかありません。

ゲームの動作を変更するには、次の3つの方法があります。

1.制限されたAPIを使用する


プラグインを作成すると、 Wotg.Plugins.Simpleオブジェクトのインスタンスは、画像の変更、要素の移動、サウンドの変更など、最も簡単な操作を実行できる基本的な方法でWotg.Plugins.Simpleます。このような操作はシンプルなプラグインに使用されます。



2.イベントを購読する


膨大な数のイベントを購読することもできます。 イベントとは、サーバーからメッセージを受信し、ボタンを押して、新しい画面を開くことを意味します。 これにより、関連するイベントに対応できます。たとえば、スペースバーを押すと、Katyushaプラグインのように、すべての武器で敵を攻撃できます。

3.積極的な変化


これは最も難しい方法ですが、最も奥深い方法でもあります(私が意味することを知っているなら;))。 前のオプションを呼び出すことができるクラスのメソッドを変更できます。 例については、サードパーティのサーバーでリプレイを保存できるプラグインの一部を参照してください。 この場合、ReplayManagerのsaveメソッドが変更されます。

 plugin.refactor( Wotg.Utils.ReplayManager, { save: function method (battle) { method.previous.call(this, battle); var replay, xhr; replay = this.getCompiledDataFrom(battle); xhr = new XMLHttpRequest(); xhr.open("POST", MY_OWN_REPLAYS_SERVER, true); xhr.send( "player=" + replay.player.name + "&opponent=" + replay.opponent.name + "&replay=" + JSON.stringify(replay) ); } }); 


これにより、ゲーム内マップジェネレーターなどの新しい機能を記述するまで、動作を変更できます。



これは、プラグインコードの観点からです。 しかし、これらすべてを接続性の観点から整理する方法はありますか?

物語


当初(数年前)、ブラウザに組み込まれたアドオンとchrome.google.com/webstoreaddons.mozilla.org/uk/firefoxなどの公式ストアを使用することが決定されました。 しかし、これには問題がありました。 ゲームが開始されるまで、そのようなプラグインを開発することは困難でした-ユーザーのためにストアに追加することはできません。 その結果、プレイヤーはゲームフォーラムのトピックに投稿されたコードをコピーアンドペーストする必要がありました。 クラシックウィンドウの代わりにunsafeWindowを使用することは、開発者を混乱させました。 そして、unsafeWindowで追加の禁止が登場しました。 一般的に、暗い時期であり、どこかに移動する必要があることが明らかになりました。

進歩的で便利なものが欲しかった。 そして、GitHubを使用することになりました。 ゲームリポジトリへのコミットおよびプールリクエスト用の1つのリポジトリ。 ユーザビリティは大幅に向上しましたが、GitHubページの非常に長い更新と便利な管理の欠如という2つの問題が発生しました。 しかし、動きの方向が正しいことは明らかでした。 そして、私たちの約束の土地がどこにあるかはすでに明らかでした。

Gitlab


サーバーでGitLabを作成し、プラグインに完全に割り当てました。 そしてそれは神でした。 スキームは次のとおりです。

-GitLabユーザーがいます-プラグイン作成者
-各ユーザーにはリポジトリがあります-プラグインごとに1つ
-リポジトリは複数のブランチを持つことができます。 たとえば、マスターと不安定。 マスターはデフォルトでオンになっています。

その結果、次の機能が得られます。

-リポジトリ全体は管理上の管理下にあり、サーバーの稼働時間と共通しています。
- Owner:Title:Branch名の形式。 たとえば、 Shock:MyCoolPluginがメインプラグインであり、 Shock:MyCoolPlugin:Unstableが開発バージョンであり、準備が完了するとウィザードにマージされます。 ファイルへのパスは、パターンによって決定されます。 gen-git.socapp.net{author}/{title}/raw/{branch}/{title}.js gen-git.socapp.net{author}/{title}/raw/{branch}/{title}.js これにより、プラグインの共同作業がさらに容易になります。ある開発者は別の開発者のリポジトリから分岐し、同じ名前のプラグインを受け取りますが、作成者は異なります。 彼は変更を行い、ユーザーにプラグインのインストールを許可し、メインプラグインへのプールリクエストを作成します。
-インストール中、プラグインに関する情報はlocalStorageに書き込まれ、そのメインファイルはすべてのクラスをロードした後、エントリポイントを呼び出す前に毎回接続されます。
-各プラグインには、対象となるゲームのバージョンがあり、更新プログラムがリリースされると、作成者が対応するブランチのバージョンを変更するまで自動的にオフになり、インストールされているすべてのユーザーに対してプラグインが自動的に再びオンになります。 この場合、次のバージョンはスーパーテストで事前に準備することができ、更新リリース中に1つのボタンでWebインターフェースを介してフリーズすることができます。
-プラグインコードでは、requireを記述するだけで十分であり、必要なプラグイン(依存関係)が自動的にプルアップされます。 それらは正しい順序で締められ、以下に示すようにプラグイン本体からアクセスできます。
-includeを使用して追加のプラグインクラスを含めることもできます。 このようなもの:

 new Wotg.Plugins.Simple({ version: '0.6.0', require: [ 'Another:Plugin' ], include: [ 'AnotherClass' ], }, function (plugin, events, required) { console.log( required['Another:Plugin'] ); //     console.log( plugin.included['AnotherClass'] ); //     }); 

plugin.addStyles( 'my.css' )使用して、スタイルを接続します。
-各プラグインには独自の設定があり、 plugins.getConfig( 'index' )コマンドで取得できます。
-最も単純なプラグインはGitLab Webインターフェースを介して変更でき、より複雑なプラグインはgit cloneおかげでローカルで開発できます。 これを行うには、テンプレートを使用してnginxを設定するだけで十分ですゲームの設定のおかげで、対応するディレクトリがプラグインリポジトリとして使用されます。 そして、接続されたプラグインのディレクトリの変更は、開発者のゲームでコミットすることなく表示されます。
-GitLabにはAPIがあります。 偽のユーザーが登録され、そのプライベートトークンのおかげで、すべてのゲームWebクライアントがAPIにリクエストを送信できます。 これにより、プラグインの検索、名前の検証などが可能になります。

 # plugins add Test:CardCreate No such plugin. Did you mean: - Shock:CardCreate # plugins add Test:Ca Min plugin title length is 4: Test:Ca # plugins add Test:Card No such plugin. Did you mean: - Shock:CardCreate # plugins add Test:Exa Min plugin title length is 4: Test:Exa # plugins add Test:Exam No such plugin. Did you mean: - Shock:Example - Isk1n:Example # plugins add Shock:Unknown No such plugin, I dont know, what you want to install # plugins add Shock:Example:Test213 No such plugin. Did you mean: - Shock:Example:master - Shock:Example:new-test 


コンソールとGUI


現時点では、プラグインのすべての管理とインストールは、Ctrl〜で開くゲーム内コンソールを介して行われます。 誰にとっても非常に便利です(ただし、ユーザーはチルダの場所を尋ねる場合があります)。 しかし、遠い計画ではGUIの作成があります-localStorageからインストールされたプラグインのリストを取得し、GitLab APIのおかげでそれらの検索を実装し、それらに関する情報を表示します。

興味がある人は、開発者向けドキュメントを読んだり、プラグインのセクションを参照したり、 WoT:Generalsでその外観を確認したりできます。

実装は非常に単純なので、コードの観点から具体的には実装を含めませんでした。 私にとって最も興味深いのは、 GitLabをパッケージマネージャーとして使用することです。 しかし、技術的な実装やアイデアについて質問がある場合は、コメントをお待ちしています。

Source: https://habr.com/ru/post/J271357/


All Articles