Posted June 14, 20205 yr Ive been trying to create a custom projectile entity, and the entity kinda works, but i cant get it to render properly. It wont render at all. My Classes: Note, most of the entity code comes from the vanilla fireball Abstract projectile package com.mekelaina.gramarye.entities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.projectile.ProjectileHelper; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.network.IPacket; import net.minecraft.network.play.server.SSpawnObjectPacket; import net.minecraft.particles.IParticleData; import net.minecraft.particles.ParticleTypes; import net.minecraft.util.DamageSource; import net.minecraft.util.math.*; import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; public abstract class AbstractBoltEntity extends Entity { public LivingEntity shootingEntity; private int ticksAlive; private int ticksInAir; public double accelerationX; public double accelerationY; public double accelerationZ; protected AbstractBoltEntity(EntityType<? extends AbstractBoltEntity> entityType, World world) { super(entityType, world); } public AbstractBoltEntity(EntityType<? extends AbstractBoltEntity> EntityType, double x, double y, double z, double xAccIn, double yAccIn, double zAccIn, World world) { this(EntityType, world); this.setLocationAndAngles(x, y, z, this.rotationYaw, this.rotationPitch); this.setPosition(x, y, z); double d0 = (double) MathHelper.sqrt(xAccIn * xAccIn + yAccIn * yAccIn + zAccIn * zAccIn); this.accelerationX = xAccIn / d0 * 0.1D; this.accelerationY = yAccIn / d0 * 0.1D; this.accelerationZ = zAccIn / d0 * 0.1D; } public AbstractBoltEntity(EntityType<? extends AbstractBoltEntity> entityType, LivingEntity shootingEntityIn, double xAccIn, double yAccIn, double zAccIn, World world) { this(entityType, world); this.shootingEntity = shootingEntityIn; this.setLocationAndAngles(shootingEntityIn.posX, shootingEntityIn.posY, shootingEntityIn.posZ, shootingEntityIn.rotationYaw, shootingEntityIn.rotationPitch); this.setPosition(this.posX, this.posY, this.posZ); this.setMotion(Vec3d.ZERO); xAccIn = xAccIn + this.rand.nextGaussian() * 0.4D; yAccIn = yAccIn + this.rand.nextGaussian() * 0.4D; zAccIn = zAccIn + this.rand.nextGaussian() * 0.4D; double d0 = (double) MathHelper.sqrt(xAccIn * xAccIn + yAccIn * yAccIn + zAccIn * zAccIn); this.accelerationX = xAccIn / d0 * 0.1D; this.accelerationY = yAccIn / d0 * 0.1D; this.accelerationZ = zAccIn / d0 * 0.1D; } @OnlyIn(Dist.CLIENT) public boolean isInRangeToRenderDist(double distance) { double d0 = this.getBoundingBox().getAverageEdgeLength() * 4.0D; if (Double.isNaN(d0)) { d0 = 4.0D; } d0 = d0 * 64.0D; return distance < d0 * d0; } /** * Called to update the entity's position/logic. */ public void tick() { if (this.world.isRemote || (this.shootingEntity == null || !this.shootingEntity.removed) && this.world.isBlockLoaded(new BlockPos(this))) { super.tick(); ++this.ticksInAir; RayTraceResult raytraceresult = ProjectileHelper.func_221266_a(this, true, this.ticksInAir >= 25, this.shootingEntity, RayTraceContext.BlockMode.COLLIDER); if (raytraceresult.getType() != RayTraceResult.Type.MISS && !net.minecraftforge.event.ForgeEventFactory.onProjectileImpact(this, raytraceresult)) { this.onImpact(raytraceresult); } Vec3d vec3d = this.getMotion(); this.posX += vec3d.x; this.posY += vec3d.y; this.posZ += vec3d.z; ProjectileHelper.rotateTowardsMovement(this, 0.2F); float f = this.getMotionFactor(); if (this.isInWater()) { for(int i = 0; i < 4; ++i) { float f1 = 0.25F; this.world.addParticle(ParticleTypes.BUBBLE, this.posX - vec3d.x * 0.25D, this.posY - vec3d.y * 0.25D, this.posZ - vec3d.z * 0.25D, vec3d.x, vec3d.y, vec3d.z); } f = 0.8F; } this.setMotion(vec3d.add(this.accelerationX, this.accelerationY, this.accelerationZ).scale((double)f)); this.world.addParticle(this.getParticle(), this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, 0.0D); this.setPosition(this.posX, this.posY, this.posZ); } else { this.remove(); } } protected IParticleData getParticle() { return ParticleTypes.SMOKE; } /** * Return the motion factor for this projectile. The factor is multiplied by the original motion. */ protected float getMotionFactor() { return 0.95F; } /** * Called when this EntityFireball hits a block or entity. */ protected abstract void onImpact(RayTraceResult result); public void writeAdditional(CompoundNBT compound) { Vec3d vec3d = this.getMotion(); compound.put("direction", this.newDoubleNBTList(new double[]{vec3d.x, vec3d.y, vec3d.z})); compound.put("power", this.newDoubleNBTList(new double[]{this.accelerationX, this.accelerationY, this.accelerationZ})); compound.putInt("life", this.ticksAlive); } /** * (abstract) Protected helper method to read subclass entity data from NBT. */ public void readAdditional(CompoundNBT compound) { if (compound.contains("power", 9)) { ListNBT listnbt = compound.getList("power", 6); if (listnbt.size() == 3) { this.accelerationX = listnbt.getDouble(0); this.accelerationY = listnbt.getDouble(1); this.accelerationZ = listnbt.getDouble(2); } } this.ticksAlive = compound.getInt("life"); if (compound.contains("direction", 9) && compound.getList("direction", 6).size() == 3) { ListNBT listnbt1 = compound.getList("direction", 6); this.setMotion(listnbt1.getDouble(0), listnbt1.getDouble(1), listnbt1.getDouble(2)); } else { this.remove(); } } /** * Returns true if other Entities should be prevented from moving through this Entity. */ public boolean canBeCollidedWith() { return true; } public float getCollisionBorderSize() { return 1.0F; } /** * Called when the entity is attacked. */ public boolean attackEntityFrom(DamageSource source, float amount) { if (this.isInvulnerableTo(source)) { return false; } else { this.markVelocityChanged(); if (source.getTrueSource() != null) { Vec3d vec3d = source.getTrueSource().getLookVec(); this.setMotion(vec3d); this.accelerationX = vec3d.x * 0.1D; this.accelerationY = vec3d.y * 0.1D; this.accelerationZ = vec3d.z * 0.1D; if (source.getTrueSource() instanceof LivingEntity) { this.shootingEntity = (LivingEntity)source.getTrueSource(); } return true; } else { return false; } } } /** * Gets how bright this entity is. */ public float getBrightness() { return 1.0F; } @OnlyIn(Dist.CLIENT) public int getBrightnessForRender() { return 15728880; } public IPacket<?> createSpawnPacket() { int i = this.shootingEntity == null ? 0 : this.shootingEntity.getEntityId(); return new SSpawnObjectPacket(this.getEntityId(), this.getUniqueID(), this.posX, this.posY, this.posZ, this.rotationPitch, this.rotationYaw, this.getType(), i, new Vec3d(this.accelerationX, this.accelerationY, this.accelerationZ)); } } Actual entity package com.mekelaina.gramarye.entities; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.IPacket; import net.minecraft.util.DamageSource; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.World; import net.minecraftforge.fml.network.NetworkHooks; public class SpellBoltEntity extends AbstractBoltEntity{ protected boolean doesDamage = false; protected float damageAmt = 0f; protected DamageSource damageSource = DamageSource.GENERIC; public SpellBoltEntity(EntityType<? extends AbstractBoltEntity> entityType, World world) { super(entityType, world); } /* @Override public IPacket<?> createSpawnPacket() { return NetworkHooks.getEntitySpawningPacket(this); }*/ public SpellBoltEntity(EntityType<? extends AbstractBoltEntity> entityType, LivingEntity shootingEntityIn, double xAccIn, double yAccIn, double zAccIn, World world) { super(entityType, shootingEntityIn, xAccIn, yAccIn, zAccIn, world); } @Override protected void onImpact(RayTraceResult result) { BlockPos pos = new BlockPos(result.getHitVec().x, result.getHitVec().y, result.getHitVec().z); if(shootingEntity instanceof PlayerEntity) { ((PlayerEntity) shootingEntity).sendStatusMessage(this.world.getBlockState(pos).getBlock().getNameTextComponent(), false); } this.remove(); } @Override protected void registerData() { } public boolean isDoesDamage() { return doesDamage; } public void setDoesDamage() { this.doesDamage = true; } public float getDamageAmt() { return damageAmt; } public void setDamageAmt(float damageAmt) { this.damageAmt = damageAmt; } public DamageSource getDamageSource() { return damageSource; } public void setDamageSource(DamageSource damageSource) { this.damageSource = damageSource; } } Renderer package com.mekelaina.gramarye.entities; import com.mekelaina.gramarye.Gramarye; import com.mekelaina.gramarye.entities.SpellBoltEntity; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRendererManager; import net.minecraft.util.ResourceLocation; import javax.annotation.Nullable; public class DefaultSpellBoltRenderer extends EntityRenderer<SpellBoltEntity> { private static final ResourceLocation TEXTURE = new ResourceLocation(Gramarye.MODID, "textures/entity/entitybolt2.png"); //private static final DefaultSpellBoltModel MODEL = new DefaultSpellBoltModel(); public DefaultSpellBoltRenderer(EntityRendererManager renderManager) { super(renderManager); bindTexture(TEXTURE); } @Nullable @Override protected ResourceLocation getEntityTexture(SpellBoltEntity entity) { return TEXTURE; } @Override public void doRender(SpellBoltEntity entity, double x, double y, double z, float entityYaw, float partialTicks) { super.doRender(entity, x, y, z, entityYaw, partialTicks); renderManager.renderEntity(entity, x, y, z, entityYaw, partialTicks, false); // MODEL.render(entity, 0f, 0f, 0f, entityYaw, e); } } Where its registered package com.mekelaina.gramarye.setup; import com.mekelaina.gramarye.Gramarye; import com.mekelaina.gramarye.entities.DefaultSpellBoltRenderer; import com.mekelaina.gramarye.entities.SpellBoltEntity; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.client.registry.RenderingRegistry; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; @Mod.EventBusSubscriber(modid = Gramarye.MODID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD) public class ClientSetup { public static void init(final FMLClientSetupEvent event) { } @SubscribeEvent public static void onClientSetupEvent(FMLClientSetupEvent event) { RenderingRegistry.registerEntityRenderingHandler(SpellBoltEntity.class, DefaultSpellBoltRenderer::new); } }
June 14, 20205 yr use the new registerEntityRenderingHandler that requires an entity type, and createSpawnpacket looks right
June 14, 20205 yr Author 50 minutes ago, poopoodice said: use the new registerEntityRenderingHandler that requires an entity type, and createSpawnpacket looks right what new registerEntityRenderingHandler? im using this one "RenderingRegistry.registerEntityRenderingHandler" in my client setup class. is there another one?
June 15, 20205 yr same but different parameter: RenderingRegistry.registerEntityRenderingHandler(EntityType<T> entityClass, IRenderFactory<? super T> renderFactory)
June 16, 20205 yr 15 minutes ago, Mekelaina said: @poopoodice do you have an example of how to use IRenderFactory? You should be able to just use YourEntityRenderer::new for the render factory, I believe it will work just fine as long as you have a constructor for the renderer that takes an EntityRendererManager as a parameter.
June 17, 20205 yr Author @Ugdhar But its not working, if you look at my source code i did what you said
June 17, 20205 yr 8 minutes ago, Mekelaina said: its not working Never just say "it's not working" Be descriptive what is not working, and also provide your debug.log, preferably posted on an external site (like a github gist) and then linked to here. There could very well be a clue in the log as to what is going on. *edit: also, having your code in a github repository is super helpful. If you are not familiar with it, google "getting started with github" or something similar, and figure it out, you will thank me I promise Edited June 17, 20205 yr by Ugdhar
June 17, 20205 yr Author @Ugdhar sorry, its been a day. here is a link to my repository all of the entity code is in the entities package, and the ClientSetup class is where client side stuff is registered
June 17, 20205 yr So is it throwing an error or crashing or something? You didn't share logs or explain what's going on
June 17, 20205 yr Author 5 minutes ago, Mekelaina said: @Ugdhar sorry, its been a day. here is a link to my repository all of the entity code is in the entities package, and the ClientSetup class is where client side stuff is registered heres the log
June 17, 20205 yr Author the entity wont render, and most of the time im not even sure if my wand item is actually creating the entity. and occasionally ill get the message in chat of it hitting a certain block but not consistently.
June 17, 20205 yr 16 minutes ago, Mekelaina said: the entity wont render, and most of the time im not even sure if my wand item is actually creating the entity. and occasionally ill get the message in chat of it hitting a certain block but not consistently. Well, I have yet to mess with entities myself to be completely honest, I've only tinkered with a couple mobs so far. I guess starting at the Wand part, where you have the item right click, what are those 2s for in the SpellBoltEntity constructor? To begin with I'd start looking into that.
June 17, 20205 yr Author 12 minutes ago, Ugdhar said: Well, I have yet to mess with entities myself to be completely honest, I've only tinkered with a couple mobs so far. I guess starting at the Wand part, where you have the item right click, what are those 2s for in the SpellBoltEntity constructor? To begin with I'd start looking into that. the 2s were just a constant acceleration for the entity. Most of the actual code for the projectile entity was taken from vanillas fireball code. They are used to calculate how quickly the entity should accelerate.
June 17, 20205 yr 1 hour ago, Mekelaina said: the 2s were just a constant acceleration for the entity. Most of the actual code for the projectile entity was taken from vanillas fireball code. They are used to calculate how quickly the entity should accelerate. Well, by my guess, having all 2s will make it accelerate in all 3 directions at once (X/Y/Z) in the same direction every time, and not in the direction you are looking. Again, I haven't tried doing any of this myself as of yet, so this is just a guess. You should take a look at the ghast entity maybe, and see how it launches the fireball. Just instead of in the direction of the player, have your code use the direction the player is looking. Edited June 17, 20205 yr by Ugdhar
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.