Solved Reflections problem?

Discussion in 'Plugin Development' started by Codex Arcanum, Apr 10, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    Codex Arcanum

    Code:
    private class EntityJuggernautZombie extends EntityZombie{
    
            public EntityJuggernautZombie(World world) {
                
                super(world);
                
                System.out.println("JuggernautZombie just spawned!");
                
                this.getAttributeInstance(GenericAttributes.a).setValue(40); //Max Health
                this.setHealth(40);
                
                ItemStack is = new ItemStack(Material.LEATHER_HELMET);
                LeatherArmorMeta lam = (LeatherArmorMeta) is.getItemMeta();
                lam.setColor(Color.BLACK);
                is.setItemMeta(lam);
                
                Zombie z = (Zombie) this.getBukkitEntity();
                z.getEquipment().setHelmet(is);
                
                try {
                    
                    
                    EntityZombie.class.getDeclaredField("bw").setAccessible(true);
                    EntityZombie.class.getDeclaredField("bw").set((EntityZombie) this, 5);
                } catch (Exception e) {
                    System.out.println("No bw field. Valid ones are ");
                    for(Field f : EntityZombie.class.getDeclaredFields()){
                        System.out.println(f.getName() + ": " + f.toString());
                    }
                    e.printStackTrace();
                }
                
            }
            
            @Override
            public String getName() //This will change the name in death messages along with other things
            {
                return name;
            }
            
             
            @Override
            public void dropDeathLoot(boolean flag, int i)//'i' is the looting level used and 'flag' is if it was killed by a player
            {
                this.world.getWorld().dropItem(this.getBukkitEntity().getLocation(), new ItemStack(Material.IRON_INGOT));
            }
            
        }
    
    I'm having an issue spawning this custom entity. I know for a fact that the field 'bw' in EntityZombie both exists, and is private. When I try to modify it with reflections, it throws the following IllegalAccessException.
    Code:
    [17:57:51 WARN]: java.lang.IllegalAccessException: Class me.codex_arcanum.herebemonsters.JuggernautZombie$EntityJuggernautZombie can not access a member of class net.minecraft.server.v1_7_R1.EntityZombie with modifiers "private"
    [17:57:51 WARN]:     at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:95)
    [17:57:51 WARN]:     at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:261)
    [17:57:51 WARN]:     at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:253)
    [17:57:51 WARN]:     at java.lang.reflect.Field.doSecurityCheck(Field.java:983)
    [17:57:51 WARN]:     at java.lang.reflect.Field.getFieldAccessor(Field.java:927)
    [17:57:51 WARN]:     at java.lang.reflect.Field.set(Field.java:680)
    [17:57:51 WARN]:     at me.codex_arcanum.herebemonsters.JuggernautZombie$EntityJuggernautZombie.<init>(JuggernautZombie.java:68)
    [17:57:51 WARN]:     at me.codex_arcanum.herebemonsters.JuggernautZombie.<init>(JuggernautZombie.java:34)
    [17:57:51 WARN]:     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    [17:57:51 WARN]:     at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
    [17:57:51 WARN]:     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    [17:57:51 WARN]:     at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
    [17:57:51 WARN]:     at me.codex_arcanum.herebemonsters.Executor.onCommand(Executor.java:25)
    [17:57:51 WARN]:     at org.bukkit.command.PluginCommand.execute(PluginCommand.java:44)
    [17:57:51 WARN]:     at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:196)
    [17:57:51 WARN]:     at org.bukkit.craftbukkit.v1_7_R1.CraftServer.dispatchCommand(CraftServer.java:542)
    [17:57:51 WARN]:     at net.minecraft.server.v1_7_R1.PlayerConnection.handleCommand(PlayerConnection.java:932)
    [17:57:51 WARN]:     at net.minecraft.server.v1_7_R1.PlayerConnection.a(PlayerConnection.java:814)
    [17:57:51 WARN]:     at net.minecraft.server.v1_7_R1.PacketPlayInChat.a(PacketPlayInChat.java:28)
    [17:57:51 WARN]:     at net.minecraft.server.v1_7_R1.PacketPlayInChat.handle(PacketPlayInChat.java:47)
    [17:57:51 WARN]:     at net.minecraft.server.v1_7_R1.NetworkManager.a(NetworkManager.java:146)
    [17:57:51 WARN]:     at net.minecraft.server.v1_7_R1.ServerConnection.c(SourceFile:134)
    [17:57:51 WARN]:     at net.minecraft.server.v1_7_R1.MinecraftServer.u(MinecraftServer.java:655)
    [17:57:51 WARN]:     at net.minecraft.server.v1_7_R1.DedicatedServer.u(DedicatedServer.java:250)
    [17:57:51 WARN]:     at net.minecraft.server.v1_7_R1.MinecraftServer.t(MinecraftServer.java:545)
    [17:57:51 WARN]:     at net.minecraft.server.v1_7_R1.MinecraftServer.run(MinecraftServer.java:457)
    [17:57:51 WARN]:     at net.minecraft.server.v1_7_R1.ThreadServerApplication.run(SourceFile:617)
    
    I don't see why I'm getting this exception after using Field.setAccessible(true).

    Alright, further information.
    Code:
    EntityZombie.class.getDeclaredField("bw").setAccessible(true);
    EntityZombie.class.getDeclaredField("bw").set((EntityZombie) this, 5);
    
    became
    Code:
    EntityZombie.class.getDeclaredField("bw").setAccessible(true);
    System.out.println(EntityZombie.class.getDeclaredField("bw").isAccessible());
    EntityZombie.class.getDeclaredField("bw").set((EntityZombie) this, 5);
    
    And this debug line printed out false. Whaaaaa...?

    Figured out what the issue is. I needed to be using the same reference to the field object. Solved it by doing
    Code:
    Field f = EntityZombie.class.getDeclaredField("bw");
    f.setAccessible(true);
    f.set((EntityZombie) this, 5);
    
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 7, 2016
Thread Status:
Not open for further replies.

Share This Page