Solved Extending a custom entity spawns invisible.

Discussion in 'Spigot Plugin Development' started by funnyrick01, Jun 29, 2018.

  1. So i'm trying to spawn my custom boss zombie. For this i've extended the class EntityZombie to remove some of the default zombie pathfinding. However, when i try to add the entity to the world it becomes totally invisible. the server can't even see it as an entity but you can hear him and damage it with projectiles. My code for the custom zombie is:
    Code (Text):
    public class CustomZombie extends EntityZombie {
        public CustomZombie(World world) {
            super(((CraftWorld) world).getHandle());
        }
    }
    And the code for the boss is:
    Code (Text):
    public class Charger extends CustomZombie {
        public Charger(Location location) {
            super(location.getWorld());
        }
    }
    Now this code does work when creating a new instance like:
    Code (Text):
    CustomZombie customZombie = new CustomZombie(location.getWorld());
    customZombie.setPosition(location.getX(), location.getY(), location.getZ());
    customZombie.world.addEntity(customZombie, SpawnReason.CUSTOM);
    But when creating a new instance of my boss class the zombie doesn't appear to be an entity to the server.
    Code (Text):
    Charger c = new Charger(location.getWorld());
    c.setPosition(location.getX(), location.getY(), location.getZ());
    c.world.addEntity(c, SpawnReason.CUSTOM);


    It creates the zombie. i can hear it walk and it can be damaged by using projectiles. But it's totally invisible to the player and the server. For example if i preform the command "/kill @e" it will not get killed.

    I'm currently lost at what this could possibly be. Now my only conclusions are either there is a bug in java itself, or EntityZombie breaks when extended twice. But both options seem very unlikely. Could anyone help me with this one? please :cry:
     
  2. Does it throw any errors?
     
  3. no, the invisible zombie works just like a normal zombie.
     
  4. FrostedSnowman

    Resource Staff

    you need to register your custom entity
     
    • Agree Agree x 1
  5. I already do this. It fully works without any problem what so ever with "new CustomZombie(location.getWorld());". But i would like it to work when i create a new instance of a class that extends CustomZombie
     
  6. Well, I've messed with custom entities myself on multiple occasions, and I can tell you this: It's not an uncommon problem. If you botch just about anything in creating one, you'll end up with invisi-pseudo-existant entity that you described.

    One thing I'm curious about: In the EntityZombie, you have it take a World as an argument, whereas the Charger you have take a Location, yet I'm not seeing you changing your code to accommodate this when you create a Charger vs an EntityZombie? You appear to pass a World to both, I think, or am I missing something?
     
  7. About the world argument, it's a small mistake while posting this thread. In my actual code i am passing through the right arguments.

    And for the invisible zombie, would you know any way to fix it? Or work around it?
    One way that i tried and worked was to simply not extend CustomZombie and just add it as a variable. But this is a very dirty fix, and i would like it as clean as possible.
     
  8. To be honest, I remember days of head-wall-slamming working on fixing stuff like that. I never double-extended something like this, and I would never want to; I've never had legitimate need to create an entity to then base an entity off of. My advice for this if you can't work out a solution (because I remember causing the invisible-entity thing so many times doing so many things that I can't even begin to tell you the possible causes), is to just make it slightly less pretty and have it be a variable. It's slightly sloppier, sure, but if you're legitimately making so many changes to the original zombie to warrant a double-extended boss class based off your new version, then you're probably a good enough coder to make it work relatively smoothly with either two entities that both extend the base zombie, or a boolean within the CustomZombie class that identifies it as a boss.

    I know that's not the nice answer, but it's either that or you get the pleasure of doing what I do: Try literally everything that pops into your head for a few hours, or in some cases, a few sittings across a few days, until it just works and you go "huh, so that weird thing I just did is what I need. Good to know."

    My most favorite example of this was fixing shift auto-dismounting you from entities. It took me a combined effort of somewhere in the ballpark of 5 hours before the right combination of listeners and NMS-looping magically made it work like I wanted to :p Sometimes it's just playing with the thing until it works, and that's especially the case in working with custom NMS entities, which are about as finicky as Bukkit gets short of some uglier database and / or Bungee stuff, in my experience.
     
    #8 OutOfTime, Jun 29, 2018
    Last edited: Jun 29, 2018
  9. Thanks for your awnser, at least i now know it's not just one of my brain farts XD. I guess i'll just go with a workaround for now. It's actually a very small project anyways so i don't feel like head-wall-slamming for 2 days for this.

    EDIT:
    Perhaps it was one of my brain farts... When i tried to have the boss class extend ZombieEntity directly it still didn't work and i realized i did not register the boss class to be a entity. I only registerd the CustomZombie class. But that's not sufficient enough when you want to extend it.
     
    #9 funnyrick01, Jun 30, 2018
    Last edited: Jun 30, 2018
  10. Can you post your code for registering the custom entity?
     
  11. Code (Text):
        @Override
        public void onEnable() {
            NMSUtils.registerEntity("custom_zombie", NMSUtils.Type.ZOMBIE, CustomZombie.class, false);
            NMSUtils.registerEntity("charger", NMSUtils.Type.ZOMBIE, Charger.class, false);
        }
    And i used a small library for registering custom entities. https://www.spigotmc.org/threads/1-...registering-custom-nms-entities-items.235431/
    Code (Text):
        /**
         * Registers the custom class to be available for use.
         *
         * @param name
         *            - The 'savegame id' of the mob.
         * @param type
         *            - The type of your mob
         * @param customClass
         *            - Your custom class that'll be used
         * @param override
         *            - Should your mob be set as a default in each biome? Only one custom entity of this type entity can
         *            have this set as 'true'.
         * @see #registerEntity(int, String, MobType, Class, Biome[])
         * @see EntityType#getName() EntityType#getName() for the savegame id.
         */
        @SuppressWarnings("unchecked")
        public static void registerEntity(String name, Type type, Class<? extends Entity> customClass, boolean override) {
            MinecraftKey key = new MinecraftKey(name);
            EntityTypes.b.a(type.getId(), key, customClass);
            if (!EntityTypes.d.contains(key)) {
                EntityTypes.d.add(key);
            }
            if (!override || type.isSpecial()) {
                return;
            }
            Field field;
            if ((field = type.getMeta().getField()) == null) {
                return;
            }
            try {
                field.setAccessible(true);
                for (BiomeBase base : NMSUtils.BIOMES) {
                    List<BiomeMeta> list = (List<BiomeMeta>) field.get(base);
                    for (BiomeMeta meta : list) {
                        if (meta.b == type.getNMSClass()) {
                            meta.b = (Class<? extends EntityInsentient>) customClass;
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
     
  12. That class is a bit overkill for what you are doing. Here is a link to a more basic version. Also your problem is probably cause your constructors are wrong. Replace them with this:
    Code (Java):
    public class CustomEntityNameHere extends EntityZombie {
        public CustomEntityNameHere(net.minecraft.server.v1_12_R1.World world) {
            super(world);
        }
    }
    Also you create a new instance like this:
    Code (Java):
    CustomEntityNameHere zombie = new CustomEntityNameHere(((CraftWorld)loc.getWorld()).getHandle());
     
    #12 AgainstTheNight, Jun 30, 2018
    Last edited: Jun 30, 2018