Posted August 30, 20223 yr 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 August 30, 20223 yr by Luckydel
August 30, 20223 yr 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.
August 30, 20223 yr Author 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.
August 31, 20223 yr 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.
August 31, 20223 yr 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 August 31, 20223 yr by perromercenary00
August 31, 20223 yr Author 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 August 31, 20223 yr by Luckydel
August 31, 20223 yr 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.
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.