プレイヤーとして、ゲームの「拡張機能」(別名mod)の作成と使用に関して次の問題を発見しました。
1)ゲームが更新されるたびに、すべてのModが壊れます。
2)ほとんどのMODは互いに機能しないため、プレイヤーは「選択する必要があります」
3)modをアンインストールした場合、「保存したゲーム」はほとんどの場合使用できなくなります。
これらの問題を示さないScala/Javaでゲームを設計したいと思います。ポイント2のサポートが必要です。最大限に拡張できるように書きたいと思います。私の問題は、これをどのように行うべきかを適切に特定できないことです。また、設計全体がコンポーネント/サービス/プラグインアーキテクチャの上にあるため、この問題を解決するまで先に進むことができません。
私が達成したいデザインの品質は次のとおりです。
1)「サービス」については、それを実装する単一のオブジェクトが(いつでも)存在する必要があります。サイクルベースのシミュレーションなので、サイクル間で安全に「実装を入れ替える」ことができます。
2)「サードパーティ」が「サービス」の機能を変更または拡張する可能性が高い「バンドル」を作成し、実行時に既存のアプリケーションに「バインド」できるようにする必要がありますなし再コンパイル。
3)これらのバンドルは長時間実行されるサーバーで使用されるため、実行時にロードおよびアンロードできる必要があります。
4)拡張機能の開発は、「ジュニア」プログラマーであっても、複雑なフレームワークに関する広範な知識を必要とせずに、簡単に可能である必要があります。
5)severalバンドルは、ほとんどの競合を防ぐ特定のルールセットに従っている限り、同じサービスを同時に拡張/変更できるはずです。
私は最初にOSGiを使用することを計画していましたが、これを機能させる方法がよくわかりません。 OSGiソリューションは、多くのバンドルに同じサービスを登録させ、「フィルター」を使用してクライアントコードで1つを選択することです。いつでも、同じサービスのさまざまなバリエーションを実装するオブジェクトが複数存在する可能性があり、それらのインスタンスが行き来する可能性があることをコードに認識させると、すべてが非常に複雑で脆弱になります。
私の計画は、すべてのサービスを汎用の「ハンドル」として登録することでした。これを使用して、サービスのユーザーは実際のインスタンスを取得し、必要なものにキャストできます。ハンドルの内容は時間の経過とともに変化する可能性がありますが、ハンドルオブジェクト自体はプログラムの期間中有効であるため、関連するフィルタリングを使用して、レジストリの定期的なクエリをバイパスします。
OSGiは2から5を解決できると思いますが、同じサービスの複数のインスタンスを使用することによってのみ、1とは矛盾します。1は、構成を使用するか、サービスのすべての異なる実装をに融合することによって達成されると思います。バイトコード操作による単一のオブジェクト。 Javaassistを見ると、クラスがすべて同じ基本クラスを拡張し、同じコンストラクターパラメーターを使用する場合、クラスの「リベース」はそれほど難しくないように思われることがわかりました。一方、構成は、サードパーティの拡張機能開発者の手にはるかに多くの作業を費やしているようです。これは4と矛盾しており、一般的にはせいぜい不格好なソリューションです。
バイトコード操作戦略を実装する場合、基本的にほとんどすべてを自分で行う必要があり、OSGiの利点のほとんどを失うことになります。また、すべてのバンドルがアクティブ化されるまで、実際には融合サービスを作成できないため、アクティブ化時に「実際の」サービスインスタンスを登録できません。これがOSGiの目的です(?)。 OSGiから、いつ「完了」したかさえわかりますか?
これらの設計目標を達成する唯一の方法は、独自のコンポーネントフレームワークを作成することですか、それともOSGiやその他のシステムを使用してそれを行うことはできますか?そのレベルでホイールを再発明することは愚かな(そして時間のかかる)アイデアのように聞こえますが、OSGiでこれらの問題を解決する方法がわかりません。多分別のサービス/プラグインフレームワークがそれを行うことができますか?または、特定の明確に定義された設計戦略を使用することによって?
更新:OpenGLで実行されるインターネットクライアントサーバー(クラスター)モデルになります。私はほとんど「フレームワークの邪魔にならない」、つまり、自分のニーズに合ったものを選択できますが、JVMに固執したいと思っています。 OSGiは、JVMの「コンポーネント」(バンドルと呼ばれる)を標準化する試みです。
概念的に言えば、コンポーネントプログラミングを扱いたいと考えています。この場合、コードのセクションが別のセクションに置き換えられたり、コードの新しい同様のセクションが実行時に追加、削除、または更新されます。
http://en.wikipedia.org/wiki/Component-based_software_engineering
使用しているプログラミング言語とプログラミングフレームワークに応じて、これを行うためのいくつかの方法について読みました。 「JavaFramework」や「ScalaFramework」でのやり方は無視します。
(C/C++とObjectPascal(Delphi)、およびネットワークWindowzeの「共有ライブラリ」で同様のことを行いました)
そのゲームまたはアプリケーションは、ネットワーク、インターネット、またはスタンドアロンのデスクトップアプリになります。 ?
これは、Webページ(javascript)、フラッシュコントロール、またはSwingやSWTなどのデスクトップインターフェイスで実行することを目的としていますか?
「コンポーネント駆動型」アプリケーションを実装するテクノロジー。これは、ある「プラットフォーム」または環境とは大きく異なります。
プログラミング言語側では、この「バンドル」または「コンポーネント」のほとんどは、同じクラスを共有するか、同じインターフェイスを実装するオブジェクトです。
Java Swingは、アクションハンドラーを使用してこの問題を処理します。各コンポーネントは、1つ以上のアクションハンドラーを使用して自身を登録します。特定のアクションが発生すると、登録された各コンポーネントは、アクションに応答してコードを実行する機会を得ます。
同様のアイデアはメッセージングシステムです。コンポーネントは、メッセージを受信するために登録します。コンポーネントは、選択したメッセージに応答する責任があります。
これらのアイデアは両方とも、残りのコードベースにアクセスできるコンポーネントに依存しています。ゲームのすべてのフィールドとインスタンスを公開するのに最適な方法がわかりません。明確に定義されたゲームプログラマーインターフェイスのセットが最良の方法だと思います。
古いゲームDarkForces 2:JediKnightにはこの問題はありませんでした。基本的に、すべてのゲームアセットは1つの場所に保存されていました。アセットを追加して使用することができ(アセットをオーバーライドしない限り...たとえばスキンを置き換える)、すべてがおかしなものでした。カスタムステージ/アセットを一意の名前で参照する必要がありました。これは適切な設計であり、アセットIDの一部としてパック名が含まれています。
私があなたの質問をひどく誤解しているなら、私に知らせてください、しかしこれはあなたが直面していることに有効なアプローチだと思います。