Solved 1.17.1 Custom Entity always spawns as a pig

Discussion in 'Plugin Development' started by FoxinatorDev, Sep 6, 2021.

  1. Offline

    FoxinatorDev

    Whenever I spawn my custom entity, it's always a pig, even though in the entity class the constructor and super constructor has the Zombie entity type. I'm not really sure why this is happening or ways to fix this. I'm also using Mojang mappings.

    Things I've already tried:
    - Making EntityBossTestZombie extend Zombie (EntityZombie)
    - Changing MobCategory to CREATURE instead of MONSTER

    CustomEntityType.java:
    Code:
    public record CustomEntityType<T extends Entity>(String name,
                                                     EntityType<? extends Entity> model,
                                                     EntityType<T> entityType) {
        @ParametersAreNonnullByDefault
        public CustomEntityType {
        }
    
        public static final CustomEntityType<EntityBossTestZombie> TEST_ZOMBIE = register("test_zombie", EntityType.ZOMBIE, EntityType.Builder.of(EntityBossTestZombie::new, MobCategory.MONSTER).sized(0.6F, 1.95F).clientTrackingRange(8));
    
        private static List<CustomEntityType<? extends Entity>> entities = new ArrayList<>();
    
        @SuppressWarnings("unchecked")
        public static void unregisterEntities() {
            for (CustomEntityType<? extends Entity> info : entities) {
                var name = info.name();
                var location = ResourceLocation.tryParse(name);
                assert location != null;
    
                var typeMap = (Map<Object, Type<?>>) DataFixers.getDataFixer().getSchema(DataFixUtils.makeKey(SharedConstants.getCurrentVersion().getWorldVersion())).findChoiceType(References.ENTITY).types();
                typeMap.remove(location.toString());
    
                System.out.println("Unregistered entity " + name);
            }
        }
    
        @SuppressWarnings("all")
        private static <R extends Entity> CustomEntityType<R> register(String name, EntityType<? extends Entity> model, EntityType.Builder builder) {
            var type = (EntityType) builder.build(name);
            var info = new CustomEntityType<>(name, model, type);
    
            registerEntity(name, model, type);
            addEntity(info);
          
            return info;
        }
    
        @SuppressWarnings("unchecked")
        private static <R extends Entity> void registerEntity(String name, EntityType<? extends Entity> model, EntityType<R> type) {
            var location = ResourceLocation.tryParse(name);
            assert location != null;
    
            var typeMap = (Map<Object, Type<?>>) DataFixers.getDataFixer().getSchema(DataFixUtils.makeKey(SharedConstants.getCurrentVersion().getWorldVersion())).findChoiceType(References.ENTITY).types();
            var entityLocation = ResourceLocation.tryParse(((TranslatableComponent)model.getDescription()).getKey());
            assert entityLocation != null;
    
            System.out.println(entityLocation.getPath()); // entity.minecraft.<mob>
            System.out.println("minecraft:" + entityLocation.getPath().split("\\.")[2]); // minecraft:<mob>
            typeMap.keySet().forEach(System.out::println); // Just to make sure I had the right format
          
            typeMap.put(location.toString(), typeMap.get("minecraft:" + entityLocation.getPath().split("\\.")[2]));
            Registry.register(Registry.ENTITY_TYPE, name, type);
    
            System.out.println("Registered entity " + name);
        }
    
        @SuppressWarnings("unchecked")
        public static void registerAttributes(EntityType<? extends LivingEntity> type, AttributeSupplier supplier) {
            try {
                var attributesMapField = DefaultAttributes.class.getDeclaredField("b");
                attributesMapField.setAccessible(true);
    
                var attributesMap = (Map<EntityType<? extends LivingEntity>, AttributeSupplier>) attributesMapField.get(null);
                if (attributesMap instanceof ImmutableMap) {
                    attributesMap = new HashMap<>(attributesMap);
    
                    ReflectionUtils.setFieldUnsafe(attributesMapField, attributesMap);
                }
                attributesMap.put(type, supplier);
            } catch (NoSuchFieldException | IllegalAccessException exception) {
                exception.printStackTrace();
            }
        }
      
        public static void addEntity(CustomEntityType<? extends Entity> type) {
            if(entities == null) {
                entities = new ArrayList<>();
            }
            entities.add(type);
        }
    
        public static List<CustomEntityType<? extends Entity>> getEntities() {
            return Collections.unmodifiableList(entities);
        }
    }
    EntityBossTestZombie.java:
    Code:
    public class EntityBossTestZombie extends EntityBoss implements CustomEntity {
    
        private static final CustomEntityType<EntityBossTestZombie> TYPE = CustomEntityType.TEST_ZOMBIE;
    
        public EntityBossTestZombie(Level world) {
            this(EntityType.ZOMBIE, world);
        }
    
        public EntityBossTestZombie(EntityType<? extends Zombie> entityType, Level world) {
            super(entityType, world);
            init();
        }
    
        private void init() {
            this.bossEvent = new ServerBossEvent(getDisplayName(), BossEvent.BossBarColor.BLUE, BossEvent.BossBarOverlay.NOTCHED_12);
        }
    
        public static AttributeSupplier.Builder createAttributes() {
            return Zombie.createAttributes();
        }
    
        @Override
        protected void registerGoals() {
            this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F));
            this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
            this.addBehaviourGoals();
        }
    
        protected void addBehaviourGoals() {
            this.goalSelector.addGoal(2, new ZombieLikeAttackGoal(this, 1.0D, false));
            this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D));
            this.targetSelector.addGoal(1, (new HurtByTargetGoal(this)).setAlertOthers(ZombifiedPiglin.class));
            this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
    
            this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true));
            this.targetSelector.addGoal(5, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR));
        }
    
        @Override
        public boolean doHurtTarget(Entity entity) {
            entity.setSecondsOnFire(2);
            return super.doHurtTarget(entity);
        }
    
        @Override
        public EntityCategory getSpecies() {
            return EntityCategory.UNDEAD;
        }
    
        @Override
        public void addAdditionalSaveData(CompoundTag tag) {
            super.addAdditionalSaveData(tag);
            tag.putString("id", TYPE.name());
        }
    }
    EntityBoss.java:
    Code:
    public class EntityBoss extends PathfinderMob {
    
        protected ServerBossEvent bossEvent;
    
        public EntityBoss(EntityType<? extends PathfinderMob> entityType, Level world) {
            super(entityType, world);
        }
    
        @Override
        public void startSeenByPlayer(ServerPlayer player) {
            super.startSeenByPlayer(player);
    
            if(bossEvent == null) return;
            bossEvent.addPlayer(player);
        }
    
        @Override
        public void stopSeenByPlayer(ServerPlayer player) {
            super.stopSeenByPlayer(player);
    
            if(bossEvent == null) return;
            bossEvent.removePlayer(player);
        }
    
        @Override
        public boolean alwaysAccepts() {
            return super.alwaysAccepts();
        }
    }
    EDIT: nvm apparently you have to set the EntityType in both constructors lol

    Here's the fixed code for anyone who needs it
    Code:
    public EntityBossTestZombie(Level world) {
            this(EntityType.ZOMBIE, world);
        }
    
        public EntityBossTestZombie(EntityType<?> entityType, Level world) {
            super(EntityType.ZOMBIE, world);
            init();
        }
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited: Sep 6, 2021

Share This Page