2016-06-17 23 views
-1

これは、Minecraft Bukkit APIとも呼ばれるMinecraftサーバーのソースコードからのもので、今までと同じくらい知っています。このインターフェイスはどのようにインスタンス化されていますか?

public interface Server extends PluginMessegeRecipient { 
    public String getVersion(); 
} 

PluginMessageRecipientもインタフェースです:サーバーと呼ばれるインターフェースがあり

。彼らは、サーバーオブジェクトからメソッドを呼び出すバケットクラスの

public final class Bukkit { 
    private static Server server; 

} 

インサイド方法:

ServerのインスタンスBukkitと呼ばれるクラスがあります。例:

server.getVersion(); 

実際には、getVersionのコードはサーバーインターフェイスにはなく、メソッドシグネチャのみです。 PluginMessageRecipientインターフェイスにコードもなく、何も拡張しません。

私は匿名クラスまたは内部クラスが必要だと言っているので、すべての質問と回答を読みましたが、これはそれらのソリューションには適していないようです。

+1

の線に沿って何かをします。例: 'Bucket.server = new VersionFiveServer()'と 'VersionFiveServerがサーバを実装する '。 – CollinD

+1

サーバーはインターフェイスなので、コードはありません。メソッドシグネチャのみを持ちます。それがインタフェースです。他のクラスはそのインタフェースを実装し、コードを含みます。 – ManoDestra

+0

関連:http://stackoverflow.com/questions/383947/what-does-it-meface-to-program-to-an-interface –

答えて

1

サーバーをインスタンス化Bucketと呼ばれるクラスがあります:

実際BucketServerをインスタンス化しません。クラスBucketには、Serverへの参照が含まれています。実際のクラスがわからないように、どのように設定されているのかを示していません。

しかし、それは何がその基準(Bucket.server)に割り当てであることが保証され、それはnullないと仮定すると、Serverを実装することいくつかの具体的なクラスのオブジェクトです。そのクラスはgetVersion()の実装を提供し、それが呼び出されています。

+0

"バケットクラスにはサーバーへの参照が含まれていますが、実際のクラスがわからないように設定されている方法は表示されていません。私はそれを見ることはできません。それは私の質問です。 – nicomp

+0

それはどこかに置かれているので、 "1つではありません"は顔には偽です。あなたはそれがAPIだと言うので、間違いなくどこかでコールがあったり、設定ファイル(XML、JSON、プロパティなど)がどこかのどこかにあるコマンドラインオプションであり、どこかの初期化コードと組み合わせてクラスを実装する。あなたはまだそれを見つけていない。 APIのドキュメントを試しましたか? –

0

Bukkitは単なるModding APIです。 Bukkitを実装したい場合は、そのようなインスタンスを自分で作成してそこに渡す必要があります。

例えばBukkitが含まれてユニットテストを取る: https://github.com/Bukkit/Bukkit/blob/f210234e59275330f83b994e199c76f6abd41ee7/src/test/java/org/bukkit/TestServer.java#L77

あなたはBukkitサーバーを実行することができます実際の実装はスピゴットです。

0

私が正しく思い出すと、選択されている特定の具体的なクラスは、リフレクションによって実行時に決定されます。 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. クラスは、デフォルトのアクセス
  2. を持つクラスが一つだけのデフォルトのアクセス静的な参照を持っている自分自身へ
  3. クラスが持っています1つのデフォルトアクセス静的Stringフィールドのみです。
  4. クラスは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(); 
} 
+0

実際には、bukkitはすでに解読されていないjarファイルから動作します(CraftBukkitの他の部分はバニラコードを参照していますが、具体的な実装である 'CraftServer'はカスタムです) – Pokechu22

関連する問題