Jump to content

[1.15.2] Adding a particle track to my ProjectileItemEntity


Peerius

Recommended Posts

Hello, I just wanted my entity to have a track consisting of particles and I guess I have to do something with the tick() method of my entity. But for now the particles just spawn once when the entity is spawned. Here is my code for the tick method:

public void tick() {
			super.tick();
			if(this.world.isRemote) {
				Vec3d vec3d = this.getMotion();
		        double d0 = this.getPosX() + vec3d.x;
		        double d1 = this.getPosY() + vec3d.y;
		        double d2 = this.getPosZ() + vec3d.z;
		        this.world.addParticle(ParticleTypes.HEART, d0 - vec3d.x * 0.25D, d1 - vec3d.y * 0.25D, d2 - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z);
			}
		}

 

Thanks in advance :) 

Link to comment
Share on other sites

3 minutes ago, diesieben07 said:

Is the code actually called repeatedly? I don't see anything there that would prevent it from spawning more particles.

I'm actually calling it in the item class right here after the worldIn.playSound():

@Override
	public ActionResult<ItemStack> onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) {
		ItemStack stack = playerIn.getHeldItem(handIn);
        Vec3d look = playerIn.getLookVec();
        HeartEntity heart = new HeartEntity(1.0D,1.0D,1.0D,worldIn);
        heart.setPosition(playerIn.lastTickPosX + look.x , playerIn.lastTickPosY + look.y + 1, playerIn.lastTickPosZ + look.z);
        Vec3d vec3d = heart.getMotion();
        double d0 = heart.getPosX() + vec3d.x;
        double d1 = heart.getPosY() + vec3d.y;
        double d2 = heart.getPosZ() + vec3d.z;
        worldIn.addParticle(ParticleTypes.HEART, d0 - vec3d.x * 0.25D, d1 - vec3d.y * 0.25D, d2 - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z);
        heart.shoot(playerIn, playerIn.rotationPitch, playerIn.rotationYaw, 0.0F,1.5F,0.0F);
        if (!worldIn.isRemote) {
            worldIn.addEntity(heart);
            if(!playerIn.isCreative()) {
            stack.shrink(1);
            }
        }
        worldIn.playSound(null,playerIn.getPosition(), SoundEvents.ENTITY_SNOWBALL_THROW, SoundCategory.PLAYERS,1.0f,1.0f);
        heart.tick();
        return new ActionResult<ItemStack>(ActionResultType.SUCCESS, stack);
    }

I just don't know how to repeatedly call it the right way. I thought of a while(heart.isAlive()) because my entity get's removed when colliding with something, but then tick() get's called so fast that the entity instantly reaches it's destination. I also tried TimeUnit.MILLISECONDS.wait() with a try/catch but that caused my game to crash...

Link to comment
Share on other sites

5 minutes ago, diesieben07 said:

o.O Why are you calling the tick method?! That does not make any sense.

It will be called every tick by Minecraft. Do not call it yourself.

Okay, but then my tick() method doesn't seem to get called repeatedly. But since my entity is flying normally, it seems like the "normal" tick() method get's called.. Do you have any idea how I can change that?

Link to comment
Share on other sites

2 hours ago, diesieben07 said:

Did you check this with the debugger?

I wanted, but then this happened:

Exception in thread "main" joptsimple.MissingRequiredOptionsException: Missing required option(s) [accessToken, version]
	at joptsimple.OptionParser.ensureRequiredOptions(OptionParser.java:426)
	at joptsimple.OptionParser.parse(OptionParser.java:400)
	at net.minecraft.client.main.Main.main(SourceFile:75)
Picked up _JAVA_OPTIONS: -Xmx6144m

 

Link to comment
Share on other sites

1 hour ago, diesieben07 said:

How did you set up your workspace? It should not be called "Main".

I basically followed this tutorial on youtube, because I'm very new to modding and didn't know where to start:

(Yes, I know the title says 1.14)

 

Edit: Just tried it with the runClient.launch files etc, now it's working :) 

Edited by Peerius
Link to comment
Share on other sites

I now testet it with the debugger and came to a strange result... 

The tick() method get's called, the variables are calculated correctly, the only thing missing is the particles.

 

Edit: But I had to change the this.world.isRemote() to !this.world.isRemote()

I think this.world somehow is in the wrong world.

Edited by Peerius
Link to comment
Share on other sites

21 minutes ago, diesieben07 said:

Your entity is most likely not spawned on the client because it is not registered correctly. Post your entire entity class and your registration code.

This could be possible as my entity is invisible ?

Here is my entity class:

@ObjectHolder(DeepAffection.modid)
public class HeartEntity extends ProjectileItemEntity {
	
	@ObjectHolder("heart_entity")
	public static final EntityType<HeartEntity> HEART = RegistryHandler.HEART_ENTITY.get();
	
	   @OnlyIn(Dist.CLIENT)
	 	public HeartEntity(double x, double y, double z, World worldIn) {
	        super(HeartEntity.HEART, x, y, z, worldIn);
	    }

	 	protected HeartEntity(LivingEntity livingEntityIn, World worldIn) {
	        super(HeartEntity.HEART, livingEntityIn, worldIn);
	    }

	 	public HeartEntity(FMLPlayMessages.SpawnEntity packet, World world) {
	        super(HeartEntity.HEART, world);
	    }

	    @Override
	    public IPacket<?> createSpawnPacket() {
	        return NetworkHooks.getEntitySpawningPacket(this);
	    }

	    @Override
	    protected void onImpact(RayTraceResult result) {
	        if (result instanceof EntityRayTraceResult) {
	            EntityRayTraceResult entityRayTraceResult = (EntityRayTraceResult) result;
	            if(entityRayTraceResult.getEntity() instanceof AnimalEntity) {
	                MobEntity entity = (MobEntity) entityRayTraceResult.getEntity();
	                entity.addPotionEffect(new EffectInstance(Effects.REGENERATION,100,2));
	                this.remove();
	            } else if(entityRayTraceResult.getEntity() instanceof PlayerEntity) {
	                PlayerEntity entity = (PlayerEntity) entityRayTraceResult.getEntity();
	                entity.addPotionEffect(new EffectInstance(Effects.REGENERATION,100,2));
	                this.remove();
	            }else if(entityRayTraceResult.getEntity() instanceof MonsterEntity) {
	            	MobEntity entity = (MobEntity) entityRayTraceResult.getEntity();
	            	entity.addPotionEffect(new EffectInstance(Effects.SLOWNESS,100,10));
                    this.remove();
	            }

	        }
	        else if (result instanceof BlockRayTraceResult) {
	            BlockRayTraceResult blockRayTraceResult = (BlockRayTraceResult) result;
	            World world = this.world;
	            Block block = world.getBlockState(blockRayTraceResult.getPos()).getBlock();
	            if(block == Blocks.GRASS_BLOCK) {
	            	world.setBlockState(blockRayTraceResult.getPos(), BlockList.pink_grass_block.getDefaultState());
	            	Vec3d vec = blockRayTraceResult.getHitVec();
		            double x = vec.getX();
		            double y = vec.getY();
		            double z = vec.getZ();
		            this.setMotion(x,y,z);
		            this.remove();
	            }
	            Vec3d vec = blockRayTraceResult.getHitVec();
	            double x = vec.getX();
	            double y = vec.getY();
	            double z = vec.getZ();
	            this.setMotion(x,y,z);
	            this.remove();
	        }
	    }
	    
		public void tick() {
	        	super.tick();
	        	if(!this.world.isRemote) {
		        Vec3d vec3d = this.getMotion();
		        double d0 = this.getPosX() + vec3d.x;
		        double d1 = this.getPosY() + vec3d.y;
		        double d2 = this.getPosZ() + vec3d.z;
		        this.world.addParticle(ParticleTypes.HEART, d0 - vec3d.x * 0.25D, d1 - vec3d.y * 0.25D, d2 - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z);
		        }
		}

		@Override
		protected Item getDefaultItem() {
			return ItemList.heart;
		}
}

 

And my registration code:

public class RegistryHandler {

    public static final DeferredRegister<EntityType<?>> ENTITY_TYPES = new DeferredRegister<>(ForgeRegistries.ENTITIES, DeepAffection.modid);

    public static void init(){
        ENTITY_TYPES.register(FMLJavaModLoadingContext.get().getModEventBus());
    }

    public static final RegistryObject<EntityType<HeartEntity>> HEART_ENTITY = ENTITY_TYPES.register("heart_entity", () -> EntityType.Builder.<HeartEntity>create(EntityClassification.MISC).size(0.5F, 0.5F).build("heart_entity"));

}

 

And this could also be relevant:

@Mod("deepaffection")
public class DeepAffection {

	public static DeepAffection instance;
	public static final String modid = "deepaffection";
	private static final Logger Logger = LogManager.getLogger(modid);
	public static final ItemGroup group = new DeepAffectionItemGroup();
	
	public DeepAffection() {
		instance = this;
		
		FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
		FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientRegistries);
		
		RegistryHandler.init();
		
		MinecraftForge.EVENT_BUS.register(this);
		
	}

	private void clientRegistries(final FMLClientSetupEvent event) {
		DeepAffectionRenderRegistry.registryEntityRenders();
		DeepAffectionItemRender.render();
		Logger.info("clientRegistries method registred.");
	}

...

	@Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD)
	public static class RegistryEvents{

...

		@SubscribeEvent
		public void registerEntities(final RegistryEvent.Register<EntityType<?>> event)
		{
			event.getRegistry().registerAll
			(
				HeartEntity.HEART
			);
			
			Logger.info("Entities registred.");
		}
}

 

And for completeness my renderer for the entity:

@OnlyIn(Dist.CLIENT)
public class DeepAffectionRenderRegistry {
	
	public static void registryEntityRenders() {
		final Logger logger = LogManager.getLogger(DeepAffection.modid);
		
		RenderingRegistry.registerEntityRenderingHandler(RegistryHandler.HEART_ENTITY.get(), renderManager -> new SpriteRenderer<HeartEntity>(renderManager, Minecraft.getInstance().getItemRenderer()));
		logger.info("Entity render registerd.");
	}
}

 

Edited by Peerius
Link to comment
Share on other sites

51 minutes ago, diesieben07 said:

You are already using DeferredRegister to register your entities...?

You are right, thank you. I removed this section.

52 minutes ago, diesieben07 said:

Also do not use @OnlyIn.

Also removed.. found this somewhere in vanilla code.. I guess it was LlamaSpitEntity.

53 minutes ago, diesieben07 said:

This doesn't make sense. Either assign the field yourself or use @ObjectHolder, not both. If you do assign it yourself, do not do it in a static initializer.

*Sigh* I think I have big comprehension problems concerning this topic. I have changed it to the following:

public final EntityType<HeartEntity> HEART = RegistryHandler.HEART_ENTITY.get();

But then I had the error "Cannot refer to an instance field HeartEntity.HEART while explicitly invoking a constructor" in the constructors and that's why I changed them to:

public HeartEntity(double x, double y, double z, World worldIn) {
	        super(RegistryHandler.HEART_ENTITY.get(), x, y, z, worldIn);
	    }

and I think that's wrong as well, but I had no better solution..

 

Since you said, HarryTalks has no idea what he's talking about - Can you recommend tutorials? I don't want to annoy anyone in this forum with my java problems, because I'm currently learning it.

Link to comment
Share on other sites

18 minutes ago, diesieben07 said:

Minecraft modding teaches quite a few bad practices in Java actually.

I'd love to see a list of these so i can share them with people who try to learn Java by learning how to mod.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

34 minutes ago, diesieben07 said:

Learning Java with modding is a bad idea.

No, I'm not learning modding with java, but I'm learning it in my studies, but I don't have that much experience yet and I also noticed that modding is quite different to other programming projects.

34 minutes ago, diesieben07 said:

But I have heard good things about McJty's.

Okay, thank you :)

34 minutes ago, diesieben07 said:

Thats perfectly fine.

It also works.. but the particles still not spawn yet and my entity is still invisible.

Edited by Peerius
Link to comment
Share on other sites

4 hours ago, diesieben07 said:

You now created a mods.toml file in bin/main/META-INF. That makes no sense. The mods.toml needs to be stored in src/main/resources/META-INF.

Just found it there in my documents.. but it's also there. Changed it now.

Link to comment
Share on other sites

On 4/9/2020 at 4:49 PM, diesieben07 said:

Then your entity is not registered properly and/or does not have its spawning packet set up correctly.

I guess it's because of a wrong registration. This is where I register my entity currently:

public class RegistryHandler {

    public static final DeferredRegister<EntityType<?>> ENTITY_TYPES = new DeferredRegister<>(ForgeRegistries.ENTITIES, DeepAffection.modid);

    public static void init(){
        ENTITY_TYPES.register(FMLJavaModLoadingContext.get().getModEventBus());
    }

    public static final RegistryObject<EntityType<HeartEntity>> HEART_ENTITY = ENTITY_TYPES.register("heart_entity", () -> EntityType.Builder.<HeartEntity>create(EntityClassification.MISC).size(0.5F, 0.5F).build("heart_entity"));

}

But I read in other posts that the register part should somehow look like this:

public static final RegistryObject<EntityType<HeartEntity>> HEART_ENTITY = ENTITY_TYPES.register("heart_entity", () -> EntityType.Builder.create(HeartEntity::new, EntityClassification.MISC).size(0.5F, 0.5F).build("heart_entity"));

However this doesn't works like I thought it would.. In the create method part I get the error:

"Cannot infer type argument(s) for <T> create(EntityType.IFactory<T>, EntityClassification)"

and in the HeartEntity::new part I get:

"The type HeartEntity does not define HeartEntity(EntityType<Entity>, World) that is applicable here"

What have I done wrong? In other posts in this forum it seems like it worked like this...:/

Link to comment
Share on other sites

14 hours ago, TrazorMC said:

For your first error, you need to infer type arguments, <HeartEntity>, before the create method.

Your HeartEntity needs to have a constructor with EntityType and World parameters.

That fixed everything,  thank you! :) 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

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