Posted November 26, 20177 yr 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.
November 30, 20177 yr 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/
November 30, 20177 yr Author Thanks, good to have affirmation that I'm not doing anything wrong with the projectile itself. I'll have a look through my registration code and try to find any problems.
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.