Jump to content

Projectile entity is displayed incorrectly


Luckydel

Recommended Posts

I use:

@OnlyIn(value = Dist.CLIENT, _interface = ItemSupplier.class)
public class BulletEntity extends AbstractArrow implements ItemSupplier{
	public BulletEntity(EntityType<? extends BulletEntity> type, LivingEntity entity, Level world) {
        super(type, entity, world);
    }
	Bla-bla-bla
		BulletEntity entitybullet = new BulletEntity(ForgeModEntities.BULLETENTITY.get(), entity, world);
		entitybullet.shoot(entity.getViewVector(1).x, entity.getViewVector(1).y, entity.getViewVector(1).z, POWER, spreading);
	//...
}

Where:

POWER = 4f

POWER = 5f and >5f

I would like to make the projectile with more power and without visual bugs.

Perhaps I should somehow manually move the entity through ticks or override shoot() and play around with vectors

Edited by Luckydel
Link to comment
Share on other sites

Please provide the entire entity, item, and entity renderer class. The above provides no view on the issue.

Additionally, there does not seem to be any visual bugs. If you're talking about the inaccuracy of the bullets, that's the result of `Projectile#shoot` offsetting the look vector by some amount. It is much more noticeable with smaller projectiles.

Finally, do not use `@OnlyIn`. You should have no need to use it as `ItemSupplier` is not a client only interface.

Link to comment
Share on other sites

Entity 

Spoiler
public class BulletEntity extends AbstractArrow implements ItemSupplier{
    public BulletEntity(PlayMessages.SpawnEntity packet, Level world) {
        super(ForgeModEntities.BULLETENTITY.get(), world);
    }
    public BulletEntity(Level p_36866_, LivingEntity p_36867_) {
        super(ForgeModEntities.BULLETENTITY.get(), p_36867_, p_36866_);
    }
    public BulletEntity(EntityType<? extends BulletEntity> type, Level world) {
        super(type, world);
    }

    public BulletEntity(EntityType<? extends BulletEntity> type, double x, double y, double z, Level world) {
        super(type, x, y, z, world);
    }

    public BulletEntity(EntityType<? extends BulletEntity> type, LivingEntity entity, Level world) {
        super(type, entity, world);
    }
    public static BulletEntity shoot(Level world, LivingEntity entity, float power, double damage, int knockback, RegistryObject<SoundEvent> soundName, float spreading) {
        BulletEntity entitybullet = new BulletEntity(ForgeModEntities.BULLETENTITY.get(), entity, world);//
        //BulletEntity entitybullet = new BulletEntity(world,entity);
        //entitybullet.shootFromRotation(entity,(float)entity.getViewVector(1).x, (float)entity.getViewVector(1).y, (float)entity.getViewVector(1).z, power*2, spreading);
        entitybullet.shoot(entity.getViewVector(1).x, entity.getViewVector(1).y, entity.getViewVector(1).z, power, spreading);
        entitybullet.setSilent(true);
        entitybullet.setCritArrow(false);
        entitybullet.setBaseDamage(damage);
        entitybullet.setKnockback(knockback);
        world.addFreshEntity(entitybullet);
        world.playSound(null, entity.getX(), entity.getY(), entity.getZ(),
                soundName.get(), SoundSource.PLAYERS, 1, 1.0F / (world.getRandom().nextFloat() * 0.4F + 1.2F) * 0.5F);
        return entitybullet;
    }
    @Override
    public Packet<?> getAddEntityPacket() {
        return NetworkHooks.getEntitySpawningPacket(this);
    }

    @Override
    @OnlyIn(Dist.CLIENT)
    public ItemStack getItem() {
        return ItemStack.EMPTY;
    }

    @Override
    protected ItemStack getPickupItem() {
        return ItemStack.EMPTY;
    }

    @Override
    protected void doPostHurtEffects(LivingEntity entity) {
        super.doPostHurtEffects(entity);
        entity.setArrowCount(entity.getArrowCount() - 1);
    }

    @Override
    public void tick() {
        super.tick();
        if (this.inGround)
            this.discard();
    }
}

 

Item class
 

Spoiler
public class Makarov extends GunShotItem{
    private static final float power = 6f;
    private static final double damage = 3f;
    private static final int knockback = 1;
    private static final float spreading = 2;
    private static final int ammoInt = 8;
    private static final RegistryObject<SoundEvent> soundFire = ForgeModSounds.makarov;
    private static final RegistryObject<SoundEvent> soundReload = ForgeModSounds.reload;
    private static final RegistryObject<SoundEvent> soundEmpty = ForgeModSounds.empty;
    //////////////////////////////////////////////////////////////////////////////////////////////
    private static final float zoom = 0.7F;
    private static final float slowdownMovingLeftClick = -0.05F;
    public static float posX_OnePerson = -0.436F;
    public static float posY_OnePerson = 0.211F;
    public static float posZ_OnePerson = 0.5F;
    //////////////////////////////////////////////////////////////////////////////////////////////
    public Makarov(Item.Properties settings) {
        super(settings,power,damage,knockback,spreading,ammoInt,soundFire,soundReload,soundEmpty,zoom,slowdownMovingLeftClick,posX_OnePerson
        ,posY_OnePerson,posZ_OnePerson);
    }
    //////////////////////////////////////////////////////////////////////////////////////////////

}

 

Spoiler
public class GunShotItem extends ProjectileWeaponItem{
    private static float power;
    private static double damage;
    private static int knockback;
    private static float spreading;
    private static RegistryObject<SoundEvent> soundFire;
    private static RegistryObject<SoundEvent> soundReload;
    private static RegistryObject<SoundEvent> soundEmpty;
    private static  float zoom;
    private static  float slowdownMovingLeftClick;
    public static float posX_OnePerson;
    public static float posY_OnePerson;
    public static float posZ_OnePerson;
    public GunShotItem(Item.Properties settings, float power, double damage, int knockback, float spreading,int ammoInt
    ,RegistryObject<SoundEvent> soundFire, RegistryObject<SoundEvent> soundReload, RegistryObject<SoundEvent> soundEmpty
    ,float zoom, float slowdownMovingLeftClick, float posX_OnePerson, float posY_OnePerson, float posZ_OnePerson) {
        super(settings.durability(ammoInt));
        this.power = power;
        this.damage = damage;
        this.knockback = knockback;
        this.spreading = spreading;
        this.soundFire = soundFire;
        this.soundReload = soundReload;
        this.soundEmpty = soundEmpty;
        this.zoom = zoom;
        this.slowdownMovingLeftClick = slowdownMovingLeftClick;
        this.posX_OnePerson = posX_OnePerson;
        this.posY_OnePerson = posY_OnePerson;
        this.posZ_OnePerson = posZ_OnePerson;
    }
    ///////////////////////////////////////////////////////////Рендеринг/////////////////////////
    @SubscribeEvent
    public static void AttackLeftClick(InputEvent.InteractionKeyMappingTriggered event){
        ItemStack itemstack = Minecraft.getInstance().player.getItemInHand(event.getHand());
        //event.setSwingHand()
        if(itemstack.getItem()== ForgeModItems.MAKAROV.get()) {
            if (event.isAttack()) {
                leftOn = switchLeftOn(leftOn);
            }
            if (event.isUseItem()) {
                fl = fl + 0.1F;
            }
        }
    }
    private static AttributeInstance attributeInstance;
    private static UUID uuid = UUID.fromString("91ACAA56-401D-1156-742C-6A13A2825816");
    private static AttributeModifier attributeModifier = new AttributeModifier(uuid,"MOVEMENT_SPEED", slowdownMovingLeftClick, AttributeModifier.Operation.ADDITION);
    @SubscribeEvent
    public static void renderGUI(RenderGuiOverlayEvent.Pre event){
        if(!WM_Disable_AimCommand.check) {
            if (leftOn && VanillaGuiOverlay.CROSSHAIR.type() == event.getOverlay()) {
                event.setCanceled(true);
            }
        }
    }
    @SubscribeEvent
    public static void getPlayerTick(TickEvent.PlayerTickEvent event){

        if(event.player.getItemInHand(InteractionHand.MAIN_HAND).getItem()==ForgeModItems.MAKAROV.get()) {
            attributeInstance = event.player.getAttribute(Attributes.MOVEMENT_SPEED);
            if (leftOn    &&     attributeInstance.getModifier(uuid) != attributeModifier) {
                attributeInstance.addTransientModifier(attributeModifier);
            }
            if (!leftOn) {
                attributeInstance.removeModifier(uuid);
            }
        }

        if(WM_pos_OnePerson.check){
            event.player.sendSystemMessage(Component.translatable("pos_OnePerson: "+posX_OnePerson+"  "+posY_OnePerson+"  "+posZ_OnePerson));
        }
    }
    private static boolean switchLeftOn(boolean a){
        if(a) return false;
        else return true;
    }
    @SubscribeEvent
    public static void FOV(ComputeFovModifierEvent event){
        if(leftOn) event.setNewFovModifier(zoom);
    }
    private static float fl= -10.0F;
    private static boolean leftOn = false;
    @SubscribeEvent
    public static void DefaultItemAnimation(RenderHandEvent event){
        if(leftOn && event.getItemStack().getItem()==ForgeModItems.MAKAROV.get()){
            PoseStack poseStack = event.getPoseStack();
            poseStack.translate((double)posX_OnePerson, (double)posY_OnePerson, (double)posZ_OnePerson);
            poseStack.mulPose(Vector3f.XP.rotationDegrees((float)0));
        }
        /*
        //event.setCanceled(true);
        PoseStack poseStack = event.getPoseStack();
        InteractionHand interactionHand = event.getHand();
        ItemStack itemStack = event.getItemStack();
        //
        Minecraft minecraft = Minecraft.getInstance();
        AbstractClientPlayer abstractclientplayer = minecraft.player;
        // Сверху неуверен, и лучше получать другим способом
        /* Надо убрать когда будешь готов
        boolean flag1 = interactionHand == InteractionHand.MAIN_HAND;
        HumanoidArm humanoidarm = flag1 ? abstractclientplayer.getMainArm() : abstractclientplayer.getMainArm().getOpposite();
        boolean flag2 = humanoidarm == HumanoidArm.RIGHT;
        int k = flag2 ? 1 : -1;
        poseStack.translate((double)((float)k * -0.5F), (double)0.7F, (double)0.1F);
        //poseStack.mulPose(Vector3f.XP.rotationDegrees(-55.0F));
        //poseStack.mulPose(Vector3f.YP.rotationDegrees((float)k * 35.3F));
        //poseStack.mulPose(Vector3f.ZP.rotationDegrees((float)k * -9.785F));
        /*
        float p_109373_ = 1.0F;
        float f7 = (float)itemStack.getUseDuration() - ((float)minecraft.player.getUseItemRemainingTicks() - p_109373_ + 1.0F);
        float f11 = f7 / 10.0F;
        if (f11 > 1.0F) {
            f11 = 1.0F;
        }
        if (f11 > 0.1F) {
            float f14 = Mth.sin((f7 - 0.1F) * 1.3F);
            float f17 = f11 - 0.1F;
            float f19 = f14 * f17;
            poseStack.translate((double)(f19 * 0.0F), (double)(f19 * 0.004F), (double)(f19 * 0.0F));
        }
        poseStack.translate(0.0D, 0.0D, (double)(f11 * 0.2F));
        poseStack.scale(1.0F, 1.0F, 1.0F + f11 * 0.2F);
        poseStack.mulPose(Vector3f.YN.rotationDegrees((float)k * 45.0F));

         */
    }
    @SubscribeEvent
    public void DefaultPlayerAnimation(RenderPlayerEvent event){

    }

    ///////////////////////////////////////////////////////////ПКМ///////////////////////////////
    @Override
    public InteractionResultHolder<ItemStack> use(Level world, Player entity, InteractionHand hand) {
        ItemStack itemstack = entity.getItemInHand(hand);

        if(itemstack.getDamageValue()<8){
            entity.startUsingItem(hand);
            return new InteractionResultHolder(InteractionResult.PASS, entity.getItemInHand(hand));
        }
        if(checkAmmoAvailability(itemstack,entity)){
            world.playSound(null, entity.getX(), entity.getY(), entity.getZ(),
                    soundReload.get(), SoundSource.PLAYERS, 1, 1.0F / (world.getRandom().nextFloat() * 0.4F + 1.2F) * 0.5F);
        }
        else {
            world.playSound(null, entity.getX(), entity.getY(), entity.getZ(),
                    soundEmpty.get(), SoundSource.PLAYERS, 1, 1.0F / (world.getRandom().nextFloat() * 0.4F + 1.2F) * 0.5F);
        }
        return new InteractionResultHolder(InteractionResult.FAIL, entity.getItemInHand(hand));
    }
    @Override
    public void releaseUsing(ItemStack stack, Level world, LivingEntity user, int remainingUseTicks) {
        if (user instanceof ServerPlayer player) {
            if(true) {
                float f = 1;
                if (!world.isClientSide) {
                    //GunShotAmmo_9x8 bulletItem = (GunShotAmmo_9x8) (itemstack.getItem() instanceof GunShotAmmo_9x8 ? itemstack.getItem() : modItemType.GUNSHOTAMMO_9x8);
                    BulletEntity bull = BulletEntity.shoot(world, player, power, damage, knockback, soundFire, spreading);
                }
                stack.setDamageValue(stack.getDamageValue() + 1);
            }
        }
    }
    public boolean checkAmmoAvailability(ItemStack itemstack, Player entity){
        if(!entity.getProjectile(itemstack).isEmpty()){
            ItemStack ammo = entity.getProjectile(itemstack);
            ammo.shrink(1);
            entity.getInventory().removeItem(ammo);
            itemstack.setDamageValue(0);
            return true;
        }
        return false;
    }
    ///////////////////////////////////////////////////////////Остальное///////////////////////////////
    @Override
    public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged)
    {
        return false;
    }
    //не работает
    @Override
    public ItemStack finishUsingItem(ItemStack p_151209_, Level p_151210_, LivingEntity p_151211_) {
        return p_151209_;
    }
    //Помагает убрать анимацию атаки но создает еще проблемы
    @Override
    public boolean onEntitySwing(ItemStack stack, LivingEntity entity)
    {
        return true;
    }
    public static final Predicate<ItemStack> BULLET_ONLY = (context) -> {
        return context.is(modItemType.GUNSHOTAMMO_9x8);
    };
    public Predicate<ItemStack> getAllSupportedProjectiles() {
        return BULLET_ONLY;
    }
    public int getUseDuration(ItemStack p_40680_) {
        return 100;
    }
    public int getDefaultProjectileRange() {return 15;}
}

 

Render
 

Spoiler
public class BulletEntityRenderer extends EntityRenderer<BulletEntity> {
    private static final ResourceLocation texture = new ResourceLocation(Main.MODID, "textures/entity/bulletentity.png");
    private final BulletEntity_Model model;
    public BulletEntityRenderer(EntityRendererProvider.Context context){
        super(context);
        model = new BulletEntity_Model(context.bakeLayer(BulletEntity_Model.LAYER_LOCATION));
    }
    @Override
    public void render(BulletEntity entityIn, float entityYaw, float partialTicks, PoseStack poseStack, MultiBufferSource bufferIn, int packedLightIn) {
        VertexConsumer vb = bufferIn.getBuffer(RenderType.entityCutout(this.getTextureLocation(entityIn)));
        poseStack.pushPose();
        poseStack.mulPose(Vector3f.YP.rotationDegrees(Mth.lerp(partialTicks, entityIn.yRotO, entityIn.getYRot()) - 90));
        poseStack.mulPose(Vector3f.ZP.rotationDegrees(90 + Mth.lerp(partialTicks, entityIn.xRotO, entityIn.getXRot())));
        model.renderToBuffer(poseStack, vb, packedLightIn, OverlayTexture.NO_OVERLAY, 1, 1, 1, 0.0625f);
        poseStack.popPose();
        super.render(entityIn, entityYaw, partialTicks, poseStack, bufferIn, packedLightIn);
    }
    @Override
    public ResourceLocation getTextureLocation(BulletEntity entity) {
        return texture;
    }
}

 

Model
 

Spoiler
public class BulletEntity_Model<T extends Entity> extends EntityModel<T> {
    public static final ModelLayerLocation LAYER_LOCATION = new ModelLayerLocation(new ResourceLocation(Main.MODID, "bulletentity_model"), "main");
    public ModelPart bb_main;
    public BulletEntity_Model(ModelPart root) {
        this.bb_main = root.getChild("bb_main");
    }
    public static LayerDefinition createBodyLayer() {
        MeshDefinition meshdefinition = new MeshDefinition();
        PartDefinition partdefinition = meshdefinition.getRoot();

        PartDefinition bb_main = partdefinition.addOrReplaceChild("bb_main", CubeListBuilder.create().texOffs(0, 0)
                .addBox(-1.0F, -1.0F, 0.0F, 1.0F, 1.0F, 1.0F,
                        new CubeDeformation(0.0F)), PartPose.offset(0.0F, 24.0F, 0.0F));
        return LayerDefinition.create(meshdefinition, 16, 16);
    }
    @Override
    public void setupAnim(T entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) {

    }
    @Override
    public void renderToBuffer(PoseStack poseStack, VertexConsumer vertexConsumer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
        bb_main.render(poseStack, vertexConsumer, packedLight, packedOverlay, red, green, blue, alpha);
    }

}

 

Well, in the 2nd video, you can see that the slime is dying, but the bullet model is in a completely different place.

Link to comment
Share on other sites

1. Don't use `@OnlyIn`. It is never needed anywhere.

2. You don't need the `PlayMessages$SpawnEntity` constructor nor override `Entity#getAddEntityPacket`. You are not syncing custom information from the server when the entity is spawned.

3. Don't ever use nonfinal static fields as instance fields. That's not how instances work. Please learn Java for that.

4. Layer definitions for models need to be registered in `EntityRenderersEvent$RegisterLayerDefinitions`.

5. Entity renderers need to be registered in `EntityRenderersEvent$RegisterRenderers`.

6. Do not combine client and common code. Separate them into different classes.

7. Do not have use a class for more than one purpose (e.g. `Item`, event listener, etc.). That is separation of concerns and leads to poor programming.

8. If you want stack specific behavior, use a capability. If you want client specific behavior, you can use static or instance fields because any mod instance will only have access to at most a single physical client.

Finally, I watched the video on quarter speed and still have no idea what you're talking about. It looks like the bullet is hitting the entity.

Link to comment
Share on other sites

hay 

you have a custome shoot method 

BulletEntity shoot(Level world, LivingEntity entity, float power, double damage, int knockback, RegistryObject<SoundEvent> soundName, float spreading)

the vainilla arrow uses 
shootFromRotation(Entity le, float rot_pan, float rot_til, float left_offset, float fuerza, float precision)

may when you make your custome is passing values to left_offset thing while it must remain in 0.0F

 




 

Edited by perromercenary00
Link to comment
Share on other sites

 

Thanks for the advice, I'll fix the code. 
I registered the layer and render as you indicated.
 

Spoiler
@Mod.EventBusSubscriber(modid= Main.MODID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
public class ForgeModEntityRenderers {
	@SubscribeEvent
	public static void registerEntityRenderers(EntityRenderersEvent.RegisterRenderers event) {
		event.registerEntityRenderer(ForgeModEntities.BULLETENTITY.get(), BulletEntityRenderer::new);
	}
}

 

Spoiler
@Mod.EventBusSubscriber(modid= Main.MODID, bus = Mod.EventBusSubscriber.Bus.MOD, value = {Dist.CLIENT})
public class ForgeModModels {
	@SubscribeEvent
	public static void registerLayerDefinitions(EntityRenderersEvent.RegisterLayerDefinitions event) {
		event.registerLayerDefinition(BulletEntity_Model.LAYER_LOCATION, BulletEntity_Model::createBodyLayer);
	}
}

 


perromercenary00, thanks, I saw the error, tried to use shootFromRotation, the result is identical =(

ChampionAsh5357, I think it looks better here

 

 

Edited by Luckydel
Link to comment
Share on other sites

Ah, ok. Well, I would probably use the `ArrowRenderer` as a baseline here for figuring it out. It seems that the rendering is affected by the rotation of the player, which could be because of plenty of things in terms of rendering, though the most likely is that the rotation doesn't line up or there needs to be some additional translation / scaling.

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.