2016-07-06 9 views
0

したがって、バージョン依存クラス(Net Mincraft Server、別名NMS)を作成するためにReflectionを再度使用しようとしました。私は方法の問題に遭遇し、私はエラーが何であるか把握できません。NMS: "オブジェクトが宣言されたクラスのインスタンスではありません"エラー

public NPCReflection(UUID id, String name, World world) { 
    this.id = id; 
    this.name = name; 
    this.entityId = (int) Math.ceil(Math.random() * 1000) + 2000; 

    try { 
     Class<?> nmsServerClass = utils.getNMSClass("MinecraftServer"); 
     Class<?> nmsWorldServerClass = utils.getNMSClass("WorldServer"); 
     Class<?> obcCraftServerClass = utils.getOBCClass("CraftServer"); 
     Class<?> obcCraftWorldClass = utils.getOBCClass("CraftWorld"); 
     Class<?> nmsEntityPlayerClass = utils.getNMSClass("EntityPlayer"); 
     Class<?> nmsPlayerInteractManager = utils.getNMSClass("PlayerInteractManager"); 

     Class<?> obcServerClassInstance = obcCraftServerClass.cast(Bukkit.getServer()).getClass(); 
     Object nmsServerInstance = obcServerClassInstance.getMethod("getServer").invoke(obcServerClassInstance); 

     Class<?> obcWorldClassInstance = obcCraftWorldClass.cast(world).getClass(); 
     Object nmsWorldInstance = obcWorldClassInstance.getMethod("getHandle").invoke(obcWorldClassInstance); 

     Constructor<?> entityPlayerConstructor = nmsEntityPlayerClass.getConstructor(nmsServerClass, nmsWorldServerClass, GameProfile.class, nmsPlayerInteractManager); 
     Object entityPlayer = entityPlayerConstructor.newInstance(nmsServerInstance, nmsWorldInstance, new GameProfile(id, name), nmsPlayerInteractManager.getConstructor(nmsWorldServerClass).newInstance(nmsWorldInstance)); 

     utils.setValue(entityPlayer, "a", entityId); 

     this.entityPlayer = entityPlayer; 
    } catch (ClassNotFoundException e) { 
     e.printStackTrace(); 
    } catch (NoSuchMethodException e) { 
     e.printStackTrace(); 
    } catch (InvocationTargetException e) { 
     e.printStackTrace(); 
    } catch (IllegalAccessException e) { 
     e.printStackTrace(); 
    } catch (InstantiationException e) { 
     e.printStackTrace(); 
    } 
} 

これはエラーが発生します。 もっと正確には、この2行。

Class<?> obcServerClassInstance = obcCraftServerClass.cast(Bukkit.getServer()).getClass(); 
    Object nmsServerInstance = obcServerClassInstance.getMethod("getServer").invoke(obcServerClassInstance); 

とエラーが、私は(ないPCのATMで)記憶が正しければ、「オブジェクトが宣言されたクラスのインスタンスではありません」と言っています。

しかし、bukkit.getServerはServerオブジェクトを正しく返します。なぜそれがそれを行うのか分かりません。

これは反射のないリファレンスです。

   Bukkit.getServer().getPluginManager().registerEvents(this, this); 

      MinecraftServer nmsServer = ((CraftServer) Bukkit.getServer()).getServer(); 
      WorldServer nmsWorld = ((CraftWorld) Bukkit.getWorlds().get(0)).getHandle(); 
      npc = new EntityPlayer(nmsServer, nmsWorld, new GameProfile(UUID.fromString("c793afb5-c4b7-4fdb-a100-b761315913c4"), "PogoStick29"), new PlayerInteractManager(nmsWorld)); 

答えて

0

最初の警告:このようなリフレクションを使用しないでください。特にストレート・ストリングを使用しないでください。 enumを使用して、getXxxClassメソッドが使用する文字列を配信します。あなたは Class<?> obcServerClassInstance = obcCraftServerClass.cast(Bukkit.getServer()).getClass(); obcCraftServerClassによって表される型にどんなgetServer()リターンをキャストする最初にしようとしている、と述べた

。この型は、getServerによって返される型のクラス階層に属している必要があります。なぜその特定のクラスが必要ですか?このようにした場合、obcCraftServerClassで表されるクラスはgetServer()によって返されるスーパータイプになります。そのタイプを使用することができます。 obcCraftServerClassで表されるクラスがgetServer()によって返されたクラスのスーパータイプでない場合、あなたはうんざりしています。

このすべてを反映させることなくすべて行います。本当に。 utils.getXxxClass呼び出しによって返された型を介してオブジェクトをインスタンス化するよりも多くのリフレクションを行う必要はなく、結果のインスタンス参照をスーパータイプの変数に代入するだけです。すべてClass<?>ゴミで止めろ。

リフレクションであなたの不安定さは、維持不能な絡み合い、心痛、壊れたコードにつながるだけです。オブジェクト指向プログラミング(またはより良い、タイプ指向)を使用して、あなたはもっと幸せになります。

+0

私は、ゲームの複数のバージョンで動作するようにしたいと思っています。これが唯一のクリーンな方法です。また、あなたは反射なしで参照を見たことがありますか?私はそのクラスをキャストする必要があります! – Nick

0

私はAPIを使用しているため、なぜクラスをキャストする必要があるのか​​分かります。しかし、これが唯一のきれいな方法だと言うと、あなたは間違っています。リフレクションには多くの欠点があります:乱雑に見えます。フォローするのが難しく、コードが遅くなります(特にそのように実装された場合)。また、NMSのフィールドとメソッドにアクセスするためにリフレクションを使用しようとしている場合は、Mojangがそれぞれのリビジョンを再難読化するので、将来のバージョンではうんざりになる可能性があります。私はバージョンに応じてインターフェイスといくつかの実装を作成することをお勧めします。この方法では、新しいリビジョンごとにプラグインを更新する必要があります(メジャーバージョンごとに3つしかありません。たとえば、1_9_R11_9_R21_9_R3)がありますが、以前のバージョンで使用されていた古いコードをコピー/現在のバージョンと一致するようにクラスを再インポートし、必要に応じてそれに応じてアクセスするフィールドやメソッドを変更します(リフレクションを使用する必要があります)。 プラグインを複数のバージョンで同時に動作させるには、Mavenモジュールシステムを調べる必要があります。いくつかの独立したモジュールを作成することができます:基本プラグイン、インタフェース、実装。新しいバージョンがポップアップするたびに、新しい実装モジュールを追加するだけです。使用する必要があるモジュールを確認するには、起動時にサーバーバージョンを取得し、適切な実装に合わせます。バキットフォーラムのMbaxterは、これについての本当に素敵なチュートリアルを作った:https://bukkit.org/threads/support-multiple-minecraft-versions-with-abstraction-maven.115810/。お役に立てれば!

関連する問題