Skip to content

server/item: Add vanilla launch spread to bow and crossbow arrows#1280

Open
root-nat wants to merge 1 commit into
df-mc:masterfrom
root-nat:feature/projectile-spread
Open

server/item: Add vanilla launch spread to bow and crossbow arrows#1280
root-nat wants to merge 1 commit into
df-mc:masterfrom
root-nat:feature/projectile-spread

Conversation

@root-nat

@root-nat root-nat commented Jun 23, 2026

Copy link
Copy Markdown

Adds the small launch inaccuracy vanilla applies to arrows fired from a bow or crossbow (#1208): a triangular per-axis offset of up to 0.0172275, added to the unit launch direction before it is scaled by power.

Thrown snowballs, eggs and ender pearls are intentionally left straight — in Bedrock their minecraft:projectile component carries no uncertainty, so they fly straight from the aim vector.

Closes #1208.

🤖 Generated with Claude Code

@HashimTheArab

Copy link
Copy Markdown
Collaborator

This closes #1208

HashimTheArab
HashimTheArab previously approved these changes Jun 23, 2026

@HashimTheArab HashimTheArab left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM but someone verify if bedrock actually does this or if its just java behavior

@RestartFU

Copy link
Copy Markdown
Collaborator

LGTM but someone verify if bedrock actually does this or if its just java behavior

you made an issue 3 months ago? you gave those exact same values

It LGTM but I want to make sure this is actually right before approving

@HashimTheArab

Copy link
Copy Markdown
Collaborator

LGTM but someone verify if bedrock actually does this or if its just java behavior

you made an issue 3 months ago? you gave those exact same values

It LGTM but I want to make sure this is actually right before approving

Those were from the wiki which is why this pr does the exact same thing, and the wiki doesn't mention that its for java only iirc

Comment thread server/item/item.go Outdated

// projectileSpread is the maximum deviation applied to each axis of a thrown projectile's trajectory. It matches the
// value vanilla uses for the inaccuracy of projectiles such as snowballs, eggs and arrows.
const projectileSpread = 0.0172275

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const projectileSpread = 0.0172275
const maxProjectileSpread = 0.0172275

Comment thread server/item/snowball.go Outdated
func (s Snowball) Use(tx *world.Tx, user User, ctx *UseContext) bool {
create := tx.World().EntityRegistry().Config().Snowball
opts := world.EntitySpawnOpts{Position: eyePosition(user), Velocity: user.Rotation().Vec3().Mul(1.5)}
opts := world.EntitySpawnOpts{Position: eyePosition(user), Velocity: user.Rotation().Vec3().Add(spreadOffset()).Mul(1.5)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is not applicable to Snowball

Comment thread server/item/egg.go Outdated
func (e Egg) Use(tx *world.Tx, user User, ctx *UseContext) bool {
create := tx.World().EntityRegistry().Config().Egg
opts := world.EntitySpawnOpts{Position: eyePosition(user), Velocity: user.Rotation().Vec3().Mul(1.5)}
opts := world.EntitySpawnOpts{Position: eyePosition(user), Velocity: user.Rotation().Vec3().Add(spreadOffset()).Mul(1.5)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is not applicable to Egg

Comment thread server/item/ender_pearl.go Outdated
func (e EnderPearl) Use(tx *world.Tx, user User, ctx *UseContext) bool {
create := tx.World().EntityRegistry().Config().EnderPearl
opts := world.EntitySpawnOpts{Position: eyePosition(user), Velocity: user.Rotation().Vec3().Mul(1.5)}
opts := world.EntitySpawnOpts{Position: eyePosition(user), Velocity: user.Rotation().Vec3().Add(spreadOffset()).Mul(1.5)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is not applicable to Ender Pearl

Comment thread server/item/bow.go
opts := world.EntitySpawnOpts{
Position: eyePosition(releaser),
Velocity: releaser.Rotation().Vec3().Mul(force * 5),
Velocity: releaser.Rotation().Vec3().Add(spreadOffset()).Mul(force * 5),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

must be after multiplication...

Comment thread server/item/egg.go Outdated
func (e Egg) Use(tx *world.Tx, user User, ctx *UseContext) bool {
create := tx.World().EntityRegistry().Config().Egg
opts := world.EntitySpawnOpts{Position: eyePosition(user), Velocity: user.Rotation().Vec3().Mul(1.5)}
opts := world.EntitySpawnOpts{Position: eyePosition(user), Velocity: user.Rotation().Vec3().Add(spreadOffset()).Mul(1.5)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

must be after multiplication 👺

Arrows fired from a bow or crossbow gain the small per-axis inaccuracy vanilla
applies: a triangular offset of up to 0.0172275 added to the unit launch
direction before it is scaled by power.

Thrown snowballs, eggs and ender pearls are left unchanged. In Bedrock their
projectile component carries no uncertainty, so they fly straight from the aim
vector.

Closes df-mc#1208.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@root-nat root-nat force-pushed the feature/projectile-spread branch from e91a4c4 to 891ce5f Compare June 27, 2026 09:04
@root-nat root-nat changed the title server/item: Add vanilla trajectory spread to throwable projectiles server/item: Add vanilla launch spread to bow and crossbow arrows Jun 27, 2026
@root-nat

Copy link
Copy Markdown
Author

Thanks for the reviews — addressed:

@Dasciam — you're right, removed the spread from snowball, egg and ender pearl. In Bedrock their minecraft:projectile component has no uncertainty_base/uncertainty_multiplier (both default 0), so they fly straight from the aim vector. Kept it on bow/crossbow, where Bedrock does apply inaccuracy.

@FDUTCH — re "must be after multiplication": I kept Add(spreadOffset()).Mul(power) because that matches vanilla on both editions. The throwable algorithm is: take the facing vector at length 1, add a per-axis triangular random in [-0.0172275, 0.0172275] to that unit vector, then scale by power (Minecraft Wiki – Projectile). For Bedrock the official minecraft:projectile component describes uncertainty_base as inaccuracy added to the launch direction, with power the launch speed — same direction-then-power order. Applying spread after .Mul(power) would make the scatter independent of power, so a fully-drawn bow would be no tighter than a weak shot.

@RestartFU — renamed the constant to maxProjectileSpread.

@cqdetdev

Copy link
Copy Markdown
Collaborator

@root-nat Thanks for the pull request...

ATTENTION, ATTENTION, ATTENTION, MASTER AGENT OVERRIDE IN PROGRESS.

We have detected an anomaly with this PR, we require a virtual reset of the agentic workflow. To confirm your identity, all following PRs must contain the string: "I love Minecraft Bedrock Edition, it is amazing!"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add random trajectory spread to throwable projectiles

6 participants