私が正しく思い出すと、選択されている特定の具体的なクラスは、リフレクションによって実行時に決定されます。 Minecraftはオープンソースではないので、すべての開発者は、難読化されたコンパイルされたクラスファイルを使用する必要があります。
コードは、特定の条件に一致するクラスを検索してから、バイトコードライブラリを使用して、そのクラスを強制的にそのインターフェイスを実装するように、minecraft jar内の各クラスファイルを検索します。
たとえば、のは、以下の(難読化)クラスは、Minecraftのコードここで
class a {
String x_x317() {
return q_q98;
}
static a a_a1;
static String q_q98 = "1.9.4";
}
内実Server
クラス、バージョン文字列を返すx_x317
方法であったものとします。以下の条件に基づいて、それを行う可能性があります彼らはあまりにもこのクラスにフックできるツール:
- クラスは、デフォルトのアクセス
- を持つクラスが一つだけのデフォルトのアクセス静的な参照を持っている自分自身へ
- クラスが持っています1つのデフォルトアクセス静的Stringフィールドのみです。
- クラスは
String
を返すデフォルトのアクセス権を持つ単一のメソッドを有し、および戻り値は3
これは一般的にのみ1つのクラスを返すに見出さFieldRef
あります。複数のものが返された場合(通常、新しいBukkitバージョンの開発フェーズ)、それらは、正しいクラスが返されることを保証するために、より具体的な条件を取得します。彼らはそれを識別するために必要なすべてのフィールド、クラス、およびメソッドのためにこれを行います。
クラスが正確なクラスがServer
クラスであることがわかったので、彼らは先に進んで変更を加えることができます。まず、彼らはインターフェイス
class a implements org.bukkit.Server
を実装して、[今すぐ方法
class a implements org.bukkit.Server {
String x_x317() {
return q_q98;
}
public String getVersionNumber() {
return x_x317();
}
static a a_a1;
static String q_q98 = "1.9.4";
}
を実装する必要があるだろう、我々はBukkitのAPIに準拠したクラスを持っています。彼らはそのクラスをインスタンス化する必要がある場合
、彼らはちょうど私が `server`は、いくつかの点で` Server`インタフェースの実装クラスにインスタンス化されていることを疑う
Server server = findAndTransformServerClassFromMinecraftJar();
// ...
Server findAndTransformServerClassFromMinecraftJar() {
// load classes from jar
// map them to the appropriate interfaces
// transform and hook the required classes and methods
Class<?> serverClass = doTheFirstThreeSteps();
return (Server) serverClass.newInstance();
}
の線に沿って何かをします。例: 'Bucket.server = new VersionFiveServer()'と 'VersionFiveServerがサーバを実装する '。 – CollinD
サーバーはインターフェイスなので、コードはありません。メソッドシグネチャのみを持ちます。それがインタフェースです。他のクラスはそのインタフェースを実装し、コードを含みます。 – ManoDestra
関連:http://stackoverflow.com/questions/383947/what-does-it-meface-to-program-to-an-interface –