Jump to content

[1.12.2] Projectile not being created on the client


laton95

Recommended Posts

Hello, I have been trying to create "spell" projectiles and am running into a problem. When the projectile is created and shot it is created on the server but not on the client, causing it to not be rendered. The projectile is definitely created on the server.

 

The creation of the projectile is inside a !world.isRemote check, since all of vanilla's projectiles have this. When the check is removed the projectile is properly created and rendered, although it is desynced between client and server as expected.

 

I've been searching through vanilla's projectile code for a while now trying to find why my projectiles are different but the only thing I have found that could be related is the NetHandlerPlayClient and I haven't been able to find examples of other mods using networking when spawning entities.

 

Here is my base projectile class:

Spoiler

public abstract class SpellProjectileBase extends EntityThrowable
{

	protected boolean stationary = false;
	private ResourceLocation texture  = new ResourceLocation(ModReference.MOD_ID,
			"textures/entity/projectile/pink-purple.png");;
	private EnumParticleTypes impactParticles = EnumParticleTypes.END_ROD;;

	private float impactParticleSpeed = 2;

	public SpellProjectileBase(World worldIn)
	{
		super(worldIn);
	}

	public SpellProjectileBase(World worldIn, EntityLivingBase throwerIn)
	{
		super(worldIn, throwerIn);
	}
	
	public SpellProjectileBase(World worldIn, double x, double y, double z)
	{
		super(worldIn, x, y, z);
	}

	public ResourceLocation getTexture()
	{
		return texture;
	}
	
	@Override
	public void onUpdate()
	{
		if (world.isRemote)
		{
			LogHelper.info("update on client");
		}
		super.onUpdate();
	}

	@Override
	protected void onImpact(RayTraceResult result)
	{
		for (int i = 0; i < 16; ++i)
		{
			world.spawnParticle(impactParticles, posX, posY, posZ,
					rand.nextDouble() * impactParticleSpeed * 2 - impactParticleSpeed,
					rand.nextDouble() * impactParticleSpeed * 2 - impactParticleSpeed,
					rand.nextDouble() * impactParticleSpeed * 2 - impactParticleSpeed);
		}
		
		setDead();
	}

	protected void setImpactParticleSpeed(float projectileSpeed)
	{
		impactParticleSpeed = projectileSpeed;
	}

	protected void setStationary(boolean value)
	{
		stationary = value;
	}
}

 

 

Here is my explosive projectile example class:

Spoiler

public class SpellProjectileExplosive extends SpellProjectileBase
{

	private int power = 0;

	public SpellProjectileExplosive(World worldIn)
	{
		super(worldIn);
	}
	
	public SpellProjectileExplosive(World worldIn, EntityLivingBase throwerIn)
	{
		super(worldIn, throwerIn);
	}
	
	public SpellProjectileExplosive(World worldIn, double x, double y, double z)
	{
		super(worldIn, x, y, z);
	}

	@Override
	public void onImpact(RayTraceResult result)
	{
		if (!world.isRemote)
		{
			world.createExplosion(getThrower(), posX, posY, posZ, power, true);
		}
		
		super.onImpact(result);
	}
	
	public void setExplosivePower(int power) {
		this.power = power;
	}
}

 

 

Creation of the projectile:

Spoiler

if (!world.isRemote)
		{
			SpellProjectileExplosive projectile = new SpellProjectileExplosive(world, player);
			projectile.setExplosivePower(2);
			projectile.shoot(player, player.rotationPitch, player.rotationYaw, 0.0F, 1.5F, 1.0F);
			world.spawnEntity(projectile);
		}

 

 

I am thankful for any help.

Link to comment
Share on other sites

That's very curious. Your spawning code seems to be consistent with vanilla entities. Is it possible there is a problem with they way you registered the entity? Also, 

 

So the interesting thing is that while definitely most throwables check that they are on server before calling the spawnEntity() method, there are cases like when snowman attacks with snowball that that doesn't seem to be the case. However, all the onRightClick() methods for throwables do that check so it looks like you're doing it right.

 

In terms of the client getting information about the entity you spawn, it seems that the spawnEntity() method calls the onEntityAdded() method which seems to do the notification to all IWorldEventListenters specifically the ServerWorldEventHandler which calls the EntityTracker#track() which does the network packet. But the interesting thing is that the track() method has a very explicit if-else series to set up the tracking for all the known trackable entities and it tests using instanceof. So if you created a projectile that extended an EntitySnowball, or other throwable it would track it, but not if you extend EntityThrowable yourself. However, that is okay because there is also a call to a Forge hook to EntityRegistry.tryTrackingEntity(). 

 

The important thing here is that the tryTrackingEntity() method is where it looks it up in the registry. 

 

So basically, this is a long explanation to say that I suspect you haven't registered properly. If you think you have registered properly, you need to prove it by doing something like setting a breakpoint in the tryTrackingEntity() method and stepping through the execution to see if it is finding it and setting up the tracking properly.

 

Hope that helps.

 

 

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

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.