Jump to content

[1.12.2][SOLVED] Forcing particle effects to spawn at farther distances


Recommended Posts

Posted (edited)

I am creating an EntityThrowable that is supposed to have a medium smoke particle effect trailing it. For the most part the effect is working as intended, however the effect will stop rendering a certain distance away from the player. This distance is way too short for me, and I would like to change it, but I do not know how. I tried using the RenderGlobal particle spawning method with the ignoreRange boolean set to true, however it still will not load particles any farther.

 

EntityThrowable class:

package com.benthom123.test.entity;

import java.util.List;
import java.util.Random;
import java.util.UUID;

import javax.annotation.Nullable;

import com.benthom123.test.ModMath;

import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntityBlaze;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityThrowable;
import net.minecraft.init.Blocks;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.datafix.DataFixer;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

public class EntitySmokeShot extends EntityThrowable
{
	
    private int xTile;
    private int yTile;
    private int zTile;
    private Block inTile;
    protected boolean inGround;
    public int throwableShake;
    /** The entity that threw this throwable item. */
    protected EntityLivingBase thrower;
    private String throwerName;
    private int ticksInGround;
    private int ticksInAir;
    public Entity ignoreEntity;
    private int ignoreTime;
    private int minus;
	
	public static ResourceLocation smokeshot = new ResourceLocation("btm");
    public EntitySmokeShot(World worldIn)
    {
        super(worldIn);
        this.minus = 0;
    }

    public EntitySmokeShot(World worldIn, EntityLivingBase throwerIn)
    {
        super(worldIn, throwerIn);
    }

    public EntitySmokeShot(World worldIn, double x, double y, double z)
    {
        super(worldIn, x, y, z);
    }

    public static void registerFixesSnowball(DataFixer fixer)
    {
        EntityThrowable.registerFixesThrowable(fixer, "SmokeShot");
    }

    /**
     * Handler for {@link World#setEntityState}
     */
    @SideOnly(Side.CLIENT)
    public void handleStatusUpdate(byte id)
    {
        if (id == 3)
        {
            for (int i = 0; i < 8; ++i)
            {
                this.world.spawnParticle(EnumParticleTypes.SMOKE_NORMAL, this.posX, this.posY, this.posZ, 0.0D, 0.0D, 0.0D);
            }
        }
    }

    /**
     * Called when this EntityThrowable hits a block or entity.
     */
    protected void onImpact(RayTraceResult result)
    {
        if (result.entityHit != null)
        {
            int i = 10;

            result.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, this.getThrower()), (float)i);
        }

        if (!this.world.isRemote)
        {
            this.world.setEntityState(this, (byte)3);
            this.setDead();
        }
    }
    /**
     * Gets the amount of gravity to apply to the thrown entity with each tick.
     */
    @Override
    protected float getGravityVelocity()
    {
        return 0.0F;
    }
    
    
    @SideOnly(Side.CLIENT)
    public boolean isInRangeToRenderDist(double distance)
    {
    	return true;
    }

    
    public void onUpdate()
    {
        this.lastTickPosX = this.posX;
        this.lastTickPosY = this.posY;
        this.lastTickPosZ = this.posZ;
        super.onUpdate();

        if (this.throwableShake > 0)
        {
            --this.throwableShake;
        }

        if (this.inGround)
        {
            if (this.world.getBlockState(new BlockPos(this.xTile, this.yTile, this.zTile)).getBlock() == this.inTile)
            {
                ++this.ticksInGround;

                if (this.ticksInGround == 1200)
                {
                    this.setDead();
                }

                return;
            }

            this.inGround = false;
            this.motionX *= (double)(this.rand.nextFloat() * 0.2F);
            this.motionY *= (double)(this.rand.nextFloat() * 0.2F);
            this.motionZ *= (double)(this.rand.nextFloat() * 0.2F);
            this.ticksInGround = 0;
            this.ticksInAir = 0;
        }
        else
        {
            ++this.ticksInAir;
        }

        Vec3d vec3d = new Vec3d(this.posX, this.posY, this.posZ);
        Vec3d vec3d1 = new Vec3d(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
        RayTraceResult raytraceresult = this.world.rayTraceBlocks(vec3d, vec3d1);
        vec3d = new Vec3d(this.posX, this.posY, this.posZ);
        vec3d1 = new Vec3d(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);

        if (raytraceresult != null)
        {
            vec3d1 = new Vec3d(raytraceresult.hitVec.x, raytraceresult.hitVec.y, raytraceresult.hitVec.z);
        }

        Entity entity = null;
        List<Entity> list = this.world.getEntitiesWithinAABBExcludingEntity(this, this.getEntityBoundingBox().expand(this.motionX, this.motionY, this.motionZ).grow(1.0D));
        double d0 = 0.0D;
        boolean flag = false;

        for (int i = 0; i < list.size(); ++i)
        {
            Entity entity1 = list.get(i);

            if (entity1.canBeCollidedWith())
            {
                if (entity1 == this.ignoreEntity)
                {
                    flag = true;
                }
                else if (this.thrower != null && this.ticksExisted < 2 && this.ignoreEntity == null)
                {
                    this.ignoreEntity = entity1;
                    flag = true;
                }
                else
                {
                    flag = false;
                    AxisAlignedBB axisalignedbb = entity1.getEntityBoundingBox().grow(0.30000001192092896D);
                    RayTraceResult raytraceresult1 = axisalignedbb.calculateIntercept(vec3d, vec3d1);

                    if (raytraceresult1 != null)
                    {
                        double d1 = vec3d.squareDistanceTo(raytraceresult1.hitVec);

                        if (d1 < d0 || d0 == 0.0D)
                        {
                            entity = entity1;
                            d0 = d1;
                        }
                    }
                }
            }
        }

        if (this.ignoreEntity != null)
        {
            if (flag)
            {
                this.ignoreTime = 2;
            }
            else if (this.ignoreTime-- <= 0)
            {
                this.ignoreEntity = null;
            }
        }

        if (entity != null)
        {
            raytraceresult = new RayTraceResult(entity);
        }

        if (raytraceresult != null)
        {
            if (raytraceresult.typeOfHit == RayTraceResult.Type.BLOCK && this.world.getBlockState(raytraceresult.getBlockPos()).getBlock() == Blocks.PORTAL)
            {
                this.setPortal(raytraceresult.getBlockPos());
            }
            else
            {
                if(!net.minecraftforge.common.ForgeHooks.onThrowableImpact(this, raytraceresult))
                this.onImpact(raytraceresult);
            }
        }

        this.posX += this.motionX;
        this.posY += this.motionY;
        this.posZ += this.motionZ;
        float f = MathHelper.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ);
        this.rotationYaw = (float)(MathHelper.atan2(this.motionX, this.motionZ) * (180D / Math.PI));

        for (this.rotationPitch = (float)(MathHelper.atan2(this.motionY, (double)f) * (180D / Math.PI)); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F)
        {
            ;
        }

        while (this.rotationPitch - this.prevRotationPitch >= 180.0F)
        {
            this.prevRotationPitch += 360.0F;
        }

        while (this.rotationYaw - this.prevRotationYaw < -180.0F)
        {
            this.prevRotationYaw -= 360.0F;
        }

        while (this.rotationYaw - this.prevRotationYaw >= 180.0F)
        {
            this.prevRotationYaw += 360.0F;
        }

        this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
        this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
        float f1 = 0.99F;
        float f2 = this.getGravityVelocity();

        if (this.isInWater())
        {
            for (int j = 0; j < 4; ++j)
            {
                float f3 = 0.25F;
                this.world.spawnParticle(EnumParticleTypes.WATER_BUBBLE, this.posX - this.motionX * 0.25D, this.posY - this.motionY * 0.25D, this.posZ - this.motionZ * 0.25D, this.motionX, this.motionY, this.motionZ);
            }

            f1 = 0.8F;
        }
        
        
        this.minus++;
    	RenderGlobal renderer = Minecraft.getMinecraft().renderGlobal;
    	
        for (int k = 0; k < (12-this.minus); ++k)
        {
        	double randX = Math.random()/(this.minus/2.5);
        	double randY = Math.random()/(this.minus/2.5);
        	double randZ = Math.random()/(this.minus/2.5);
        	Random random = new Random();
            renderer.spawnParticle(12, true , ModMath.plusOrMinus(random.nextBoolean(), this.posX, randX), ModMath.plusOrMinus(random.nextBoolean(),this.posY, randY), ModMath.plusOrMinus(random.nextBoolean(), this.posZ, randZ), 0.0D, 0.0D, 0.0D);
        }
        
        
        this.motionX *= (double)f1;
        this.motionY *= (double)f1;
        this.motionZ *= (double)f1;

        if (!this.hasNoGravity())
        {
            this.motionY -= (double)f2;
        }

        this.setPosition(this.posX, this.posY, this.posZ);
    }
}

 

 

More specifically, I am overriding the getUpdate method, adding this method here to generate the particle effects:

 

        this.minus++;
    	RenderGlobal renderer = Minecraft.getMinecraft().renderGlobal;
    	
        for (int k = 0; k < (12-this.minus); ++k)
        {
        	double randX = Math.random()/(this.minus/2.5);
        	double randY = Math.random()/(this.minus/2.5);
        	double randZ = Math.random()/(this.minus/2.5);
        	Random random = new Random();
            renderer.spawnParticle(12, true , ModMath.plusOrMinus(random.nextBoolean(), this.posX, randX), ModMath.plusOrMinus(random.nextBoolean(),this.posY, randY), ModMath.plusOrMinus(random.nextBoolean(), this.posZ, randZ), 0.0D, 0.0D, 0.0D);
        }

 

 

if you guys need to see more parts of my code i can send it here or you can get it on my github: https://github.com/InterdimensionalCat/ModTest/tree/master/java/com/benthom123/test

 

Thanks for the help!

 

Edited by InterdimensionalCat
Posted

You're using the wrong spawnParticle() method. If you look in the World class you'll see there are lots of variations. The method you're using will limit the range unless the particle type's getShouldIgnoreRange() method returns true. So one fix would be for you to use custom particle type that does that. But the easier way is to use the a different spawning method.

 

There is a method called spawnAlwaysVisibleParticle() which ignores the range. There is also another spawnParticle() which takes a boolean field for ignoring the range.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted
1 hour ago, jabelar said:

You're using the wrong spawnParticle() method. If you look in the World class you'll see there are lots of variations. The method you're using will limit the range unless the particle type's getShouldIgnoreRange() method returns true. So one fix would be for you to use custom particle type that does that. But the easier way is to use the a different spawning method.

 

There is a method called spawnAlwaysVisibleParticle() which ignores the range. There is also another spawnParticle() which takes a boolean field for ignoring the range.

Thank you for the advice. However, changing to spawnAlwaysVisibleParticle() did not increase the rendering distance at all. Is it possible that the method I am performing this action in (Overriding onUpdate() in entityThrowable) is causing some type of limitation?

Posted

One thing I'm confused about in your code is that it seems you spawn particles in two different places. Are those intended for different effects, or is that because you were trying to debug?

 

In terms of code execution is also the tracking distance of the actual throwable to consider as well. how are you registering the throwable entity? 

 

Note: I think your link to your github repository is out of date, because I couldn't find any entity code there.

 

The other things to check is that when an entity is "invisible" there are three possibilities:

1) The entity is no longer tracked by the client. This is related to tracking distance. So code doesn't even run on the client.

2) The entity is tracked but the rendering isn't happening.

3) The entity is tracked and would be rendered but the position isn't where you think it should be. I don't think this is your case, but in many cases where someone says "my entity isn't spawning" it actually is but just at wrong location.

 

To debug this, it is a good idea to add console statements (System.out.println()) at critical parts of the code so you can debug the execution. That way you can determine if the updates are continuing to fire and so forth.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted (edited)
11 hours ago, jabelar said:

One thing I'm confused about in your code is that it seems you spawn particles in two different places. Are those intended for different effects, or is that because you were trying to debug?

 

In terms of code execution is also the tracking distance of the actual throwable to consider as well. how are you registering the throwable entity? 

 

Note: I think your link to your github repository is out of date, because I couldn't find any entity code there.

 

The other things to check is that when an entity is "invisible" there are three possibilities:

1) The entity is no longer tracked by the client. This is related to tracking distance. So code doesn't even run on the client.

2) The entity is tracked but the rendering isn't happening.

3) The entity is tracked and would be rendered but the position isn't where you think it should be. I don't think this is your case, but in many cases where someone says "my entity isn't spawning" it actually is but just at wrong location.

 

To debug this, it is a good idea to add console statements (System.out.println()) at critical parts of the code so you can debug the execution. That way you can determine if the updates are continuing to fire and so forth.

 

Oh, sorry, I did not realize the repository hadn't updated, here is an updated link that I checked to make sure it had all of my changes: https://github.com/InterdimensionalCat/ModTest/tree/DangerousChanges/java/com/benthom123/test

 

The first particle effect spawn in HandleStatusUpdate is working as i wanted it to, although it will not spawn at far distances like the one below it

 

The second one in onUpdate, however, is meant to follow the entity's movement; this is the one that I want to increase the rendering distance of. After adding in a Println statement like you suggested, I determined that the onUpdate method was firing way beyond the distance where the particles stopped spawning. I also changed how this.minus incremented so that at least one particle would always spawn. However the particles are still not spawning any differently.

 

Currently my tracking distance in ModEntities is 128.

 

As far as I know, this means that 1) and 2)  on your list is not the issue I am having.

 

Additionally, note that the entity model is going farther than the particle effects. That is to say, the particle effects end and the entity itself keeps going past that point, I want the particle effects to render as far as the entity renders.

 

EDIT: I have now also tried doing this in the doRender method of SmokeEntityFX (the renderer for the entity model) doing this method did not allow the particles to spawn any further. Interestingly, when in water (which causes the entity to essentially stop moving) the particles will continue to spawn from any range away from the player. This happens both when using doRender method and onUpdate method

 

EDIT 2: I Determined that the ShouldIgnoreRange  boolean was limiting my particle's range despite me using  spawnAlwaysVisibleParticle() . How would I go about making a custom particle? I am unaware of how to do this in 1.12.

Edited by InterdimensionalCat
Posted (edited)
13 hours ago, InterdimensionalCat said:

Figured it out; for some reason SpawnAlwaysVisibleParticle() is defaulting ignoreRange to false... but the SpawnParticle with a boolean condition works just fine. Thanks for your help!

You're right. That is a bug. You should report it as an issue on github MinecraftForge project.

 

EDIT: I've gone ahead and logged the issue: #4617

Edited by jabelar
  • Like 1

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Guest
This topic is now closed to further replies.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.