Option for a Glowing Layer on an Entity

Published by BToal on
Issue description

This COULD be considered a feature request, but I honestly just don't know where to post this kind of problem.

 So I'm new to this site, not really MCreator. I used it back in my early high school years, and with the Quarantine, decided to hop back on almost after 5 or so years. The program has come a LONG way from what I remember, its really quite amazing.

Anyway, I'm trying something I think would interest everyone. I want most of the mobs in my mod to have a layer, or a glowing texture. To do this, I found the Spiders layer properties, tweeked the code to match the names of my creation, and imported it into Mcreator's built in code. The problem is....I don't know how to Java haha. I don't really understand the errors it gave me (such as: not a statement, illegal start of expression, etc.), and honestly I would like some help trying to fix this, so in the future, this fix could help everyone get that glowing effect some mobs like Spiders, and Endermen have in game. Besides the unusual name given to my ideas, everything else is literally copy/paste from Minecrafts original code, with some minor tweeks here and there to what I thought made sense, but again...I'm not a coder, I like the visual side of Minecraft, the technical side isn't my forte..

Anywho, here is the locked code from the specific entity, hope someone can help with this. This wouldn't only help me, but the whole community to figure out how to accomplish this feature. Thanks in advance :)

 

ENTITY'S LOCKED CODE: (the code I added in is bolded and italicized below:) )

package net.mcreator.hyarlands.entity;

import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.fml.network.FMLPlayMessages;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.client.registry.RenderingRegistry;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.api.distmarker.Dist;

import net.minecraft.world.World;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.DamageSource;
import net.minecraft.pathfinding.FlyingPathNavigator;
import net.minecraft.item.SpawnEggItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.Item;
import net.minecraft.entity.projectile.PotionEntity;
import net.minecraft.entity.monster.MonsterEntity;
import net.minecraft.entity.ai.goal.RandomWalkingGoal;
import net.minecraft.entity.ai.goal.NearestAttackableTargetGoal;
import net.minecraft.entity.ai.goal.LookRandomlyGoal;
import net.minecraft.entity.ai.goal.Goal;
import net.minecraft.entity.ai.controller.FlyingMovementController;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.EntityClassification;
import net.minecraft.entity.Entity;
import net.minecraft.entity.CreatureAttribute;
import net.minecraft.client.renderer.model.ModelBox;
import net.minecraft.client.renderer.entity.model.RendererModel;
import net.minecraft.client.renderer.entity.model.EntityModel;
import net.minecraft.client.renderer.entity.MobRenderer;
import net.minecraft.block.Blocks;
import net.minecraft.block.BlockState;

import net.mcreator.hyarlands.entity.layers.LayerDhicoLyrnhOrbGlow;
import net.mcreator.hyarlands.procedures.LightEntityIsHurtProcedure;
import net.mcreator.hyarlands.procedures.LightEntityDiesProcedure;
import net.mcreator.hyarlands.procedures.DhicolyrnhOrbOnEntityTickUpdateProcedure;
import net.mcreator.hyarlands.HyarLandsElements;

import java.util.Random;
import java.util.EnumSet;

@HyarLandsElements.ModElement.Tag
public class DhicolyrnhOrbEntity extends HyarLandsElements.ModElement {
    public static EntityType entity = null;
    public DhicolyrnhOrbEntity(HyarLandsElements instance) {
        super(instance, 148);
        FMLJavaModLoadingContext.get().getModEventBus().register(this);
    }

    @Override
    public void initElements() {
        entity = (EntityType.Builder.<CustomEntity>create(CustomEntity::new, EntityClassification.MONSTER).setShouldReceiveVelocityUpdates(true)
                .setTrackingRange(25).setUpdateInterval(3).setCustomClientFactory(CustomEntity::new).immuneToFire().size(0.5f, 0.5f))
                        .build("dhicolyrnhorb").setRegistryName("dhicolyrnhorb");
        elements.entities.add(() -> entity);
        elements.items
                .add(() -> new SpawnEggItem(entity, -12569250, -65287, new Item.Properties().group(ItemGroup.MISC)).setRegistryName("dhicolyrnhorb"));
    }

    @SubscribeEvent
    @OnlyIn(Dist.CLIENT)
    public void registerModels(ModelRegistryEvent event) {
        RenderingRegistry.registerEntityRenderingHandler(CustomEntity.class, renderManager -> {
            return new MobRenderer(renderManager, new ModelDhicolyrnhOrb_model(), 0.2f) {
                protected ResourceLocation getEntityTexture(Entity entity) {
                    return new ResourceLocation("dimension:textures/hicolyrnhrb.png");

    public RendererModel(RenderManager renderManagerIn) { 
    {
        super(renderManagerIn, new ModelRenderer(), 1.0F);
        this.addLayer(new LayerDhicoLyrnhOrbGlow(this));
    }

    /**
     * Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture.
     */
    protected ResourceLocation getEntityTexture(T entity) {
    {
        return dhicolyrnhorbTextures;
    }    
                }
            };
        });
    }

    
    public static class CustomEntity extends MonsterEntity {
        public CustomEntity(FMLPlayMessages.SpawnEntity packet, World world) {
            this(entity, world);
        }

        public CustomEntity(EntityType<CustomEntity> type, World world) {
            super(type, world);
            experienceValue = 4;
            setNoAI(false);
            enablePersistence();
            this.moveController = new FlyingMovementController(this);
            this.navigator = new FlyingPathNavigator(this, this.world);
        }

        @Override
        protected void registerGoals() {
            super.registerGoals();
            this.goalSelector.addGoal(1, new Goal() {
                {
                    this.setMutexFlags(EnumSet.of(Goal.Flag.MOVE));
                }
                public boolean shouldExecute() {
                    if (CustomEntity.this.getAttackTarget() != null && !CustomEntity.this.getMoveHelper().isUpdating()) {
                        return true;
                    } else {
                        return false;
                    }
                }

                @Override
                public boolean shouldContinueExecuting() {
                    return CustomEntity.this.getMoveHelper().isUpdating() && CustomEntity.this.getAttackTarget() != null
                            && CustomEntity.this.getAttackTarget().isAlive();
                }

                @Override
                public void startExecuting() {
                    LivingEntity livingentity = CustomEntity.this.getAttackTarget();
                    Vec3d vec3d = livingentity.getEyePosition(1);
                    CustomEntity.this.moveController.setMoveTo(vec3d.x, vec3d.y, vec3d.z, 1);
                }

                @Override
                public void tick() {
                    LivingEntity livingentity = CustomEntity.this.getAttackTarget();
                    if (CustomEntity.this.getBoundingBox().intersects(livingentity.getBoundingBox())) {
                        CustomEntity.this.attackEntityAsMob(livingentity);
                    } else {
                        double d0 = CustomEntity.this.getDistanceSq(livingentity);
                        if (d0 < 25) {
                            Vec3d vec3d = livingentity.getEyePosition(1);
                            CustomEntity.this.moveController.setMoveTo(vec3d.x, vec3d.y, vec3d.z, 1);
                        }
                    }
                }
            });
            this.goalSelector.addGoal(2, new LookRandomlyGoal(this));
            this.targetSelector.addGoal(3, new NearestAttackableTargetGoal(this, HyarnEntity.CustomEntity.class, false, false));
            this.goalSelector.addGoal(4, new RandomWalkingGoal(this, 0.8, 20) {
                @Override
                protected Vec3d getPosition() {
                    Random random = CustomEntity.this.getRNG();
                    double dir_x = CustomEntity.this.posX + ((random.nextFloat() * 2 - 1) * 16);
                    double dir_y = CustomEntity.this.posY + ((random.nextFloat() * 2 - 1) * 16);
                    double dir_z = CustomEntity.this.posZ + ((random.nextFloat() * 2 - 1) * 16);
                    return new Vec3d(dir_x, dir_y, dir_z);
                }
            });
        }

        @Override
        public CreatureAttribute getCreatureAttribute() {
            return CreatureAttribute.UNDEFINED;
        }

        @Override
        public boolean canDespawn(double distanceToClosestPlayer) {
            return false;
        }

        protected void dropSpecialItems(DamageSource source, int looting, boolean recentlyHitIn) {
            super.dropSpecialItems(source, looting, recentlyHitIn);
            this.entityDropItem(new ItemStack(Blocks.AIR, (int) (1)));
        }

        @Override
        public net.minecraft.util.SoundEvent getAmbientSound() {
            return (net.minecraft.util.SoundEvent) ForgeRegistries.SOUND_EVENTS.getValue(new ResourceLocation(""));
        }

        @Override
        public net.minecraft.util.SoundEvent getHurtSound(DamageSource ds) {
            return (net.minecraft.util.SoundEvent) ForgeRegistries.SOUND_EVENTS.getValue(new ResourceLocation("block.beacon.activate"));
        }

        @Override
        public net.minecraft.util.SoundEvent getDeathSound() {
            return (net.minecraft.util.SoundEvent) ForgeRegistries.SOUND_EVENTS.getValue(new ResourceLocation("block.beacon.deactivate"));
        }

        @Override
        protected float getSoundVolume() {
            return 1.0F;
        }

        @Override
        public void fall(float l, float d) {
        }

        @Override
        public boolean attackEntityFrom(DamageSource source, float amount) {
            int x = (int) this.posX;
            int y = (int) this.posY;
            int z = (int) this.posZ;
            Entity entity = this;
            {
                java.util.HashMap<String, Object> $_dependencies = new java.util.HashMap<>();
                $_dependencies.put("entity", entity);
                LightEntityIsHurtProcedure.executeProcedure($_dependencies);
            }
            if (source.getImmediateSource() instanceof PotionEntity)
                return false;
            if (source == DamageSource.FALL)
                return false;
            if (source == DamageSource.CACTUS)
                return false;
            if (source == DamageSource.DROWN)
                return false;
            if (source == DamageSource.LIGHTNING_BOLT)
                return false;
            return super.attackEntityFrom(source, amount);
        }

        @Override
        public void onDeath(DamageSource source) {
            super.onDeath(source);
            int x = (int) this.posX;
            int y = (int) this.posY;
            int z = (int) this.posZ;
            Entity entity = this;
            {
                java.util.HashMap<String, Object> $_dependencies = new java.util.HashMap<>();
                $_dependencies.put("x", x);
                $_dependencies.put("y", y);
                $_dependencies.put("z", z);
                $_dependencies.put("world", world);
                LightEntityDiesProcedure.executeProcedure($_dependencies);
            }
        }

        @Override
        public void baseTick() {
            super.baseTick();
            int x = (int) this.posX;
            int y = (int) this.posY;
            int z = (int) this.posZ;
            Entity entity = this;
            {
                java.util.HashMap<String, Object> $_dependencies = new java.util.HashMap<>();
                $_dependencies.put("x", x);
                $_dependencies.put("y", y);
                $_dependencies.put("z", z);
                $_dependencies.put("world", world);
                DhicolyrnhOrbOnEntityTickUpdateProcedure.executeProcedure($_dependencies);
            }
        }

        @Override
        protected void registerAttributes() {
            super.registerAttributes();
            if (this.getAttribute(SharedMonsterAttributes.ARMOR) != null)
                this.getAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(0.5);
            if (this.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED) != null)
                this.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.5);
            if (this.getAttribute(SharedMonsterAttributes.MAX_HEALTH) != null)
                this.getAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(15);
            if (this.getAttribute(SharedMonsterAttributes.ATTACK_DAMAGE) != null)
                this.getAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(5);
            this.getAttributes().registerAttribute(SharedMonsterAttributes.FLYING_SPEED);
            this.getAttribute(SharedMonsterAttributes.FLYING_SPEED).setBaseValue(0.5);
        }

        @Override
        protected void updateFallState(double y, boolean onGroundIn, BlockState state, BlockPos pos) {
        }

        @Override
        public void setNoGravity(boolean ignored) {
            super.setNoGravity(true);
        }

        public void livingTick() {
            super.livingTick();
            this.setNoGravity(true);
        }
    }

    // Made with Blockbench
    // Paste this code into your mod.
    // Make sure to generate all required imports
    public static class ModelDhicolyrnhOrb_model extends EntityModel<Entity> {
        private final RendererModel head;
        private final RendererModel outersquare;
        private final RendererModel innersquare;
        public ModelDhicolyrnhOrb_model() {
            textureWidth = 64;
            textureHeight = 64;
            head = new RendererModel(this);
            head.setRotationPoint(0.0F, 10.0F, 0.0F);
            head.cubeList.add(new ModelBox(head, 0, 24, -3.0F, -3.0F, -3.0F, 6, 6, 6, 0.0F, false));
            outersquare = new RendererModel(this);
            outersquare.setRotationPoint(0.0F, 10.0F, 0.0F);
            setRotationAngle(outersquare, -0.8727F, -1.5708F, 0.7854F);
            outersquare.cubeList.add(new ModelBox(outersquare, 0, 0, -6.0F, -6.0F, -6.0F, 12, 12, 12, 1.0F, false));
            innersquare = new RendererModel(this);
            innersquare.setRotationPoint(0.0F, 10.0F, 0.0F);
            setRotationAngle(innersquare, -0.7854F, -0.9599F, 1.8326F);
            innersquare.cubeList.add(new ModelBox(innersquare, 0, 0, -6.0F, -6.0F, -6.0F, 12, 12, 12, -1.0F, false));
        }

        @Override
        public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) {
            head.render(f5);
            outersquare.render(f5);
            innersquare.render(f5);
        }

        public void setRotationAngle(RendererModel modelRenderer, float x, float y, float z) {
            modelRenderer.rotateAngleX = x;
            modelRenderer.rotateAngleY = y;
            modelRenderer.rotateAngleZ = z;
        }

        public void setRotationAngles(Entity e, float f, float f1, float f2, float f3, float f4, float f5) {
            super.setRotationAngles(e, f, f1, f2, f3, f4, f5);
            this.head.rotateAngleZ = f2;
            this.outersquare.rotateAngleY = f2 / 20.f;
            this.innersquare.rotateAngleY = f2 / 20.f;
        }
    }
}
 

 

ENTITY'S LAYER FILE:

package net.minecraft.client.renderer.entity.layers;

import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.entity.model.RendererModel;
import net.minecraft.entity.monster.EntityModel;
import net.minecraft.client.renderer.entity.MobRenderer;
import net.minecraft.util.ResourceLocation;

public class DhicolyrhOrbGlow implements LayerRenderer<EntityModel>
{
    private static final ResourceLocation DHICOLYRHORB_GLOW = new ResourceLocation("textures/other/hicolyrnhrb_e.png");
    private final RendererModel ModelRenderer;

    public DhicolyrhOrbGlow(RendererModel ModelRendererIn)
    {
        this.ModelRenderer = ModelRendererIn;
    }

    public void doRenderLayer(EntityModel entitylivingbaseIn, float p_177141_2_, float p_177141_3_, float partialTicks, float p_177141_5_, float p_177141_6_, float p_177141_7_, float scale)
    {
        this.ModelRenderer.bindTexture(DHICOLYRHORB_GLOW);
        GlStateManager.enableBlend();
        GlStateManager.disableAlpha();
        GlStateManager.blendFunc(1, 1);

        if (entitylivingbaseIn.isInvisible())
        {
            GlStateManager.depthMask(false);
        }
        else
        {
            GlStateManager.depthMask(true);
        }

        int i = 61680;
        int j = i % 65536;
        int k = i / 65536;
        OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)j / 1.0F, (float)k / 1.0F);
        GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
        this.ModelRenderer.getMainModel().render(entitylivingbaseIn, p_177141_2_, p_177141_3_, p_177141_5_, p_177141_6_, p_177141_7_, scale);
        i = entitylivingbaseIn.getBrightnessForRender(partialTicks);
        j = i % 65536;
        k = i / 65536;
        OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)j / 1.0F, (float)k / 1.0F);
        this.ModelRenderer.func_177105_a(entitylivingbaseIn, partialTicks);
        GlStateManager.disableBlend();
        GlStateManager.enableAlpha();
    }

    public boolean shouldCombineTextures()
    {
        return false;
    }
}

Issue comments

I have tried to support this in the past, but the problem is that the glowing layer is made out of multiple parts per my knowledge:

  1. Layer texture for glowing
  2. LayerRenderer
  3. Adding layer renderer to the model

LayerRenderer interacts with the model so in fact, the modeler sw would need to add model for the render layer, at least per my limited knowledge of this part of MC code.

I suggest you repost this to the forums, so more people can see it, the tracker is only maintained by me so more people might be able to help there :)

I have found a way to do this. 2020.3 will support this from the UI :) Closing this ticket now.