Solved Trying to Override EntityExperienceOrb

Discussion in 'Plugin Development' started by Toastlawine, Jan 18, 2019.

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

    Toastlawine

    I have a class (OV_Orb) that extends the EntityExperienceOrb in which the method d(EntityHuman) is overridden. There is nothing in that method yet, except a broadcast, but if I get it to be called I know what to do. (Look if the Player is a Spectator and cancel it)
    I didnt forget to register the new Entity and there are no errors in the console but the method is not called.

    My class:

    Code:
    package tl.thewalls.overrides;
    
    import java.lang.reflect.Method;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.craftbukkit.v1_8_R1.CraftWorld;
    import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
    
    import net.minecraft.server.v1_8_R1.EntityExperienceOrb;
    import net.minecraft.server.v1_8_R1.EntityHuman;
    import net.minecraft.server.v1_8_R1.EntityTypes;
    import net.minecraft.server.v1_8_R1.World;
    
    public class OV_Orb extends EntityExperienceOrb {
    
        public OV_Orb(World world) {
            super(world);
        }
    
        public static OV_Orb spawn(Location loc) {
            World w = ((CraftWorld) loc.getWorld()).getHandle();
            OV_Orb orb = new OV_Orb(w);
            orb.setPosition(loc.getX(), loc.getY(), loc.getZ());
            w.addEntity(orb, SpawnReason.CUSTOM);
            Bukkit.broadcastMessage("test1");
            return orb;
        }
       
        @Override
        public void d(EntityHuman e) {
            Bukkit.broadcastMessage("test2");
            return;
        }
    
        public static void registerEntity() {
            try {
                Method a = EntityTypes.class.getDeclaredMethod("a", Class.class, String.class, int.class);
                a.setAccessible(true);
                a.invoke(a, OV_Orb.class, "ExperienceOrb", 2);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
       
    }
    
    The method registerEntity() is called from my Main class and the Orb is spawned in the ExpBottleEvent. The broadcast "test1" appears in the chat.
    Thanks in advance!
     
  2. Offline

    Zombie_Striker

    @Toastlawine
    Is it only the d method that is not being called? If you also override another method, are you able to broadcast a message there?
     
  3. Offline

    Toastlawine

    I tried overriding s_() - didnt work either. In the source code of spigot 1.8 which i am using you can also clearly see that the method d() is responsible for giving the Player XP.
    btw s_() is the moevent towards a Player

    Update:
    I got it to work with a different method of registrating the Custom Orb (I dont really understand how it works) and now it seems to be working but the Orb is invisible... I saw others having this problem but couldnt find a good solution for this. Im pretty sure that it has something to do with how I register it.

    Now I got this:
    Code:
    public static void registerNonInsentientEntity(String name, int id, Class<? extends Entity> typeClass, Class<? extends Entity> customClass) {
            try {
                List<Map<?, ?>> dataMaps = new ArrayList<Map<?, ?>>();
                for (Field f : EntityTypes.class.getDeclaredFields()) {
                    if (f.getType().getSimpleName().equals(Map.class.getSimpleName())) {
                        f.setAccessible(true);
                        dataMaps.add((Map<?, ?>) f.get(null));
                    }
                }
                if (dataMaps.get(2).containsKey(id)) {
                    dataMaps.get(0).remove(name);
                    dataMaps.get(2).remove(id);
                }
                Method method = EntityTypes.class.getDeclaredMethod("a", Class.class, String.class, int.class);
                method.setAccessible(true);
                method.invoke(null, customClass, name, id);
            
                for (Field f : BiomeBase.class.getDeclaredFields()) {
                    if (f.getType().getSimpleName().equals(BiomeBase.class.getSimpleName())) {
                        if (f.get(null) != null) {
    
                            for (Field list : BiomeBase.class.getDeclaredFields()) {
                                if (list.getType().getSimpleName().equals(List.class.getSimpleName())) {
                                    list.setAccessible(true);
                                    @SuppressWarnings("unchecked")
                                    List<BiomeMeta> metaList = (List<BiomeMeta>) list.get(f.get(null));
    
                                    for (BiomeMeta meta : metaList) {
                                        Field clazz = BiomeMeta.class.getDeclaredFields()[0];
                                        if (clazz.get(meta).equals(typeClass)) {
                                            clazz.set(meta, customClass);
                                        }
                                    }
                                }
                            }
    
                        }
                    }
                }
            
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    The broadcasts are now called but the orbs only appear when they merge.

    UPDATE: It works! If someone wants to see the code please write me. Thank you very much even when you just thought about this.
     
    Last edited: Jan 19, 2019
Thread Status:
Not open for further replies.

Share This Page