Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
3792831
feat(world/view_layer.go): implement block view layer
RestartFU May 11, 2026
69084c7
Update player.go
RestartFU May 11, 2026
6e63e19
Update player.go
RestartFU May 11, 2026
fa7715d
various changes
RestartFU May 11, 2026
33d3320
various changes
RestartFU May 12, 2026
7e816f3
Update player.go
RestartFU May 12, 2026
cb57e6d
Update player.go
RestartFU May 12, 2026
ae99c48
Update player.go
RestartFU May 12, 2026
ba6cea3
Update player.go
RestartFU May 12, 2026
6de1b81
Update player.go
RestartFU May 12, 2026
b659386
Update player.go
RestartFU May 13, 2026
9c4a8fc
Update player.go
RestartFU May 13, 2026
86fa646
Fix block view layer behaviour
cqdetdev May 19, 2026
df0445f
Merge branch 'master' into dan/block-view-layer
RestartFU May 20, 2026
1f2b063
Fix view layer break state refresh
cqdetdev May 20, 2026
14e5cc8
fix(player): correct block break updates
RestartFU May 25, 2026
0431b1a
Update .gitignore
RestartFU May 25, 2026
08cef40
Update player.go
RestartFU May 28, 2026
ebfe8c5
Update player.go
RestartFU May 28, 2026
e0da704
various changes
RestartFU May 28, 2026
0944c93
Preserve view-layer block semantics
RestartFU May 28, 2026
75b7590
Keep private item use non-mutating
RestartFU May 28, 2026
2412842
Mask liquid updates behind private blocks
RestartFU May 28, 2026
8af8f8c
Suppress public actions behind private blocks
RestartFU May 28, 2026
c98f0de
Advertise private override subchunks
RestartFU May 28, 2026
3fd4236
Merge branch 'master' into dan/block-view-layer
RestartFU May 28, 2026
01a0984
Refresh item-use block after handlers
RestartFU May 28, 2026
6cd74ac
Satisfy item-use lint
RestartFU May 28, 2026
7e3eff4
Avoid redundant registry precompute
RestartFU May 28, 2026
223aae4
Resend vanished private break target
RestartFU May 28, 2026
6227483
cube/trace: add BlockIntersects and BBoxIntersects methods (#1262)
HashimTheArab May 28, 2026
bb1a7a7
world/chunk: add Clone methods to chunk, subchunk, and palette (#1264)
HashimTheArab May 28, 2026
be44518
Resolve upstream chunk conflicts
RestartFU May 28, 2026
04ba75c
Update player.go
RestartFU May 28, 2026
8a2132e
various changes
RestartFU May 28, 2026
c08da57
block/grass.go: Fix bone meal duplication glitch (#1266)
Dasciam Jun 1, 2026
64d40fd
server/block: Implement bonemeal huge growth particles (#1267)
Dasciam Jun 1, 2026
a12dba4
Merge branch 'master' into dan/block-view-layer
RestartFU Jun 8, 2026
83a8f57
item/crossbow.go: Always set critical flag to match vanilla (#1270)
Dasciam Jun 9, 2026
7c30428
item/crossbow.go: Fix crossbow charging animation played even if the …
Dasciam Jun 9, 2026
8742c81
perf(world): index view layer block overrides by chunk
RestartFU Jun 14, 2026
42b05ee
fix(player): handle private block interaction edge cases
RestartFU Jun 14, 2026
06bad5d
refactor: collapse redundant view layer guards
RestartFU Jun 14, 2026
4aecd60
fix(player): extinguish private fire overrides
RestartFU Jun 14, 2026
6f16a0e
fix(player): handle private block item use events
RestartFU Jun 14, 2026
b2ba70c
docs(player): document private block break detection
RestartFU Jun 14, 2026
8c21a0f
fix(player): avoid unused private block assignment
RestartFU Jun 14, 2026
72a16a8
Merge branch 'master' into dan/block-view-layer
RestartFU Jun 14, 2026
5b79a3d
push changes
RestartFU Jun 14, 2026
050d9cc
Update view_layer.go
RestartFU Jun 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@
/world/
/players/
/resources/

# AI
.omx
8 changes: 4 additions & 4 deletions server/block/beetroot_seeds.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,16 @@ func (BeetrootSeeds) SameCrop(c Crop) bool {
}

// BoneMeal ...
func (b BeetrootSeeds) BoneMeal(pos cube.Pos, tx *world.Tx) bool {
func (b BeetrootSeeds) BoneMeal(pos cube.Pos, tx *world.Tx) item.BoneMealResult {
if b.Growth == 7 {
return false
return item.BoneMealResultNone
}
if rand.Float64() < 0.75 {
b.Growth++
tx.SetBlock(pos, b, nil)
return true
return item.BoneMealResultSmall
}
return false
return item.BoneMealResultNone
}

// UseOnBlock ...
Expand Down
6 changes: 3 additions & 3 deletions server/block/carrot.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ func (c Carrot) Consume(_ *world.Tx, co item.Consumer) item.Stack {
}

// BoneMeal ...
func (c Carrot) BoneMeal(pos cube.Pos, tx *world.Tx) bool {
func (c Carrot) BoneMeal(pos cube.Pos, tx *world.Tx) item.BoneMealResult {
if c.Growth == 7 {
return false
return item.BoneMealResultNone
}
c.Growth = min(c.Growth+rand.IntN(4)+2, 7)
tx.SetBlock(pos, c, nil)
return true
return item.BoneMealResultSmall
}

// UseOnBlock ...
Expand Down
9 changes: 5 additions & 4 deletions server/block/cocoa_bean.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package block

import (
"math/rand/v2"

"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/block/model"
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/world"
"github.com/go-gl/mathgl/mgl64"
"math/rand/v2"
)

// CocoaBean is a crop block found in jungle biomes.
Expand All @@ -20,13 +21,13 @@ type CocoaBean struct {
}

// BoneMeal ...
func (c CocoaBean) BoneMeal(pos cube.Pos, tx *world.Tx) bool {
func (c CocoaBean) BoneMeal(pos cube.Pos, tx *world.Tx) item.BoneMealResult {
if c.Age == 2 {
return false
return item.BoneMealResultNone
}
c.Age++
tx.SetBlock(pos, c, nil)
return true
return item.BoneMealResultSmall
}

// HasLiquidDrops ...
Expand Down
35 changes: 35 additions & 0 deletions server/block/cube/trace/bbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,41 @@ func BBoxIntercept(bb cube.BBox, start, end mgl64.Vec3) (result BBoxResult, ok b
return BBoxResult{bb: bb, pos: *vec, face: f}, true
}

// BBoxIntersects checks if the line segment from start to end intersects the BBox.
// Unlike BBoxIntercept, it only reports whether an intersection exists and does not
// calculate the closest hit position or face.
func BBoxIntersects(bb cube.BBox, start, end mgl64.Vec3) bool {
min, max := bb.Min(), bb.Max()
dir := end.Sub(start)
tMin, tMax := 0.0, 1.0

for axis := range 3 {
if mgl64.FloatEqual(dir[axis], 0) {
if start[axis] < min[axis] || start[axis] > max[axis] {
return false
}
continue
}

inv := 1 / dir[axis]
t1 := (min[axis] - start[axis]) * inv
t2 := (max[axis] - start[axis]) * inv
if t1 > t2 {
t1, t2 = t2, t1
}
if t1 > tMin {
tMin = t1
}
if t2 < tMax {
tMax = t2
}
if tMin > tMax {
return false
}
}
return true
}

// vec3OnLineWithX returns an mgl64.Vec3 on the line between mgl64.Vec3 a and b with an X value passed. If no such vec3
// could be found, the bool returned is false.
func vec3OnLineWithX(a, b mgl64.Vec3, x float64) *mgl64.Vec3 {
Expand Down
21 changes: 21 additions & 0 deletions server/block/cube/trace/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package trace

import (
"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/block/model"
"github.com/df-mc/dragonfly/server/world"
"github.com/go-gl/mathgl/mgl64"
"math"
Expand Down Expand Up @@ -70,3 +71,23 @@ func BlockIntercept(pos cube.Pos, src world.BlockSource, b world.Block, start, e

return BlockResult{bb: hit.BBox(), pos: hit.Position(), face: hit.Face(), blockPos: pos}, true
}

// BlockIntersects checks if the line segment from start to end intersects the block model of b at pos. Unlike
// BlockIntercept, it only reports whether an intersection exists and does not calculate the closest hit position, face,
// or bounding box.
func BlockIntersects(pos cube.Pos, src world.BlockSource, b world.Block, start, end mgl64.Vec3) bool {
m := b.Model()
switch m.(type) {
case model.Empty:
return false
case model.Solid:
return BBoxIntersects(cube.Box(0, 0, 0, 1, 1, 1).Translate(pos.Vec3()), start, end)
}

for _, bb := range m.BBox(pos, src) {
if BBoxIntersects(bb.Translate(pos.Vec3()), start, end) {
return true
}
}
return false
}
4 changes: 2 additions & 2 deletions server/block/double_flower.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ func (d DoubleFlower) FlammabilityInfo() FlammabilityInfo {
}

// BoneMeal ...
func (d DoubleFlower) BoneMeal(pos cube.Pos, tx *world.Tx) bool {
func (d DoubleFlower) BoneMeal(pos cube.Pos, tx *world.Tx) item.BoneMealResult {
dropItem(tx, item.NewStack(d, 1), pos.Vec3Centre())
return true
return item.BoneMealResultSmall
}

// NeighbourUpdateTick ...
Expand Down
6 changes: 3 additions & 3 deletions server/block/fern.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ func (g Fern) BreakInfo() BreakInfo {
}

// BoneMeal attempts to affect the block using a bone meal item.
func (g Fern) BoneMeal(pos cube.Pos, tx *world.Tx) bool {
func (g Fern) BoneMeal(pos cube.Pos, tx *world.Tx) item.BoneMealResult {
upper := DoubleTallGrass{Type: FernDoubleTallGrass(), UpperPart: true}
if replaceableWith(tx, pos.Side(cube.FaceUp), upper) {
tx.SetBlock(pos, DoubleTallGrass{Type: FernDoubleTallGrass()}, nil)
tx.SetBlock(pos.Side(cube.FaceUp), upper, nil)
return true
return item.BoneMealResultSmall
}
return false
return item.BoneMealResultNone
}

// CompostChance ...
Expand Down
10 changes: 6 additions & 4 deletions server/block/flower.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package block

import (
"math/rand/v2"
"time"

"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/entity/effect"
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/world"
"github.com/go-gl/mathgl/mgl64"
"math/rand/v2"
"time"
)

// Flower is a non-solid plant that occur in a variety of shapes and colours. They are primarily used for decoration
Expand All @@ -32,7 +33,8 @@ func (f Flower) EntityInside(_ cube.Pos, _ *world.Tx, e world.Entity) {
}

// BoneMeal ...
func (f Flower) BoneMeal(pos cube.Pos, tx *world.Tx) (success bool) {
func (f Flower) BoneMeal(pos cube.Pos, tx *world.Tx) (result item.BoneMealResult) {
result = item.BoneMealResultNone
if f.Type == WitherRose() {
return
}
Expand All @@ -54,7 +56,7 @@ func (f Flower) BoneMeal(pos cube.Pos, tx *world.Tx) (success bool) {
}
}
tx.SetBlock(p, Flower{Type: flowerType}, nil)
success = true
result = item.BoneMealResultArea
}
return
}
Expand Down
13 changes: 8 additions & 5 deletions server/block/grass.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package block

import (
"math/rand/v2"

"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/world"
"math/rand/v2"
)

// Grass blocks generate abundantly across the surface of the world.
Expand Down Expand Up @@ -78,18 +80,19 @@ func (g Grass) RandomTick(pos cube.Pos, tx *world.Tx, r *rand.Rand) {
}

// BoneMeal ...
func (g Grass) BoneMeal(pos cube.Pos, tx *world.Tx) bool {
for i := 0; i < 14; i++ {
func (g Grass) BoneMeal(pos cube.Pos, tx *world.Tx) (result item.BoneMealResult) {
result = item.BoneMealResultNone
for range 14 {
c := pos.Add(cube.Pos{rand.IntN(6) - 3, 0, rand.IntN(6) - 3})
above := c.Side(cube.FaceUp)
_, air := tx.Block(above).(Air)
_, grass := tx.Block(c).(Grass)
if air && grass {
tx.SetBlock(above, plantSelection[rand.IntN(len(plantSelection))], nil)
result = item.BoneMealResultArea
}
}

return false
return
}

// BreakInfo ...
Expand Down
9 changes: 5 additions & 4 deletions server/block/kelp.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package block

import (
"math/rand/v2"

"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/world"
"github.com/go-gl/mathgl/mgl64"
"math/rand/v2"
)

// Kelp is an underwater block which can grow on top of solids underwater.
Expand All @@ -24,7 +25,7 @@ func (k Kelp) SmeltInfo() item.SmeltInfo {
}

// BoneMeal ...
func (k Kelp) BoneMeal(pos cube.Pos, tx *world.Tx) bool {
func (k Kelp) BoneMeal(pos cube.Pos, tx *world.Tx) item.BoneMealResult {
for y := pos.Y(); y <= tx.Range()[1]; y++ {
currentPos := cube.Pos{pos.X(), y, pos.Z()}
block := tx.Block(currentPos)
Expand All @@ -36,11 +37,11 @@ func (k Kelp) BoneMeal(pos cube.Pos, tx *world.Tx) bool {
}
if water, ok := block.(Water); ok && water.Depth == 8 {
tx.SetBlock(currentPos, Kelp{Age: k.Age + 1}, nil)
return true
return item.BoneMealResultSmall
}
break
}
return false
return item.BoneMealResultNone
}

// BreakInfo ...
Expand Down
9 changes: 5 additions & 4 deletions server/block/melon_seeds.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package block

import (
"math/rand/v2"

"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/world"
"github.com/go-gl/mathgl/mgl64"
"math/rand/v2"
)

// MelonSeeds grow melon blocks.
Expand Down Expand Up @@ -62,13 +63,13 @@ func (m MelonSeeds) RandomTick(pos cube.Pos, tx *world.Tx, r *rand.Rand) {
}

// BoneMeal ...
func (m MelonSeeds) BoneMeal(pos cube.Pos, tx *world.Tx) bool {
func (m MelonSeeds) BoneMeal(pos cube.Pos, tx *world.Tx) item.BoneMealResult {
if m.Growth == 7 {
return false
return item.BoneMealResultNone
}
m.Growth = min(m.Growth+rand.IntN(4)+2, 7)
tx.SetBlock(pos, m, nil)
return true
return item.BoneMealResultSmall
}

// UseOnBlock ...
Expand Down
6 changes: 3 additions & 3 deletions server/block/pink_petals.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ type PinkPetals struct {
}

// BoneMeal ...
func (p PinkPetals) BoneMeal(pos cube.Pos, tx *world.Tx) bool {
func (p PinkPetals) BoneMeal(pos cube.Pos, tx *world.Tx) item.BoneMealResult {
if p.AdditionalCount < 3 {
p.AdditionalCount++
tx.SetBlock(pos, p, nil)
return true
return item.BoneMealResultSmall
}
dropItem(tx, item.NewStack(p, 1), pos.Vec3Centre())
return true
return item.BoneMealResultSmall
}

// UseOnBlock ...
Expand Down
6 changes: 3 additions & 3 deletions server/block/potato.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ func (p Potato) Consume(_ *world.Tx, c item.Consumer) item.Stack {
}

// BoneMeal ...
func (p Potato) BoneMeal(pos cube.Pos, tx *world.Tx) bool {
func (p Potato) BoneMeal(pos cube.Pos, tx *world.Tx) item.BoneMealResult {
if p.Growth == 7 {
return false
return item.BoneMealResultNone
}
p.Growth = min(p.Growth+rand.IntN(4)+2, 7)
tx.SetBlock(pos, p, nil)
return true
return item.BoneMealResultSmall
}

// UseOnBlock ...
Expand Down
9 changes: 5 additions & 4 deletions server/block/pumpkin_seeds.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package block

import (
"math/rand/v2"

"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/world"
"github.com/go-gl/mathgl/mgl64"
"math/rand/v2"
)

// PumpkinSeeds grow pumpkin blocks.
Expand Down Expand Up @@ -62,13 +63,13 @@ func (p PumpkinSeeds) RandomTick(pos cube.Pos, tx *world.Tx, r *rand.Rand) {
}

// BoneMeal ...
func (p PumpkinSeeds) BoneMeal(pos cube.Pos, tx *world.Tx) bool {
func (p PumpkinSeeds) BoneMeal(pos cube.Pos, tx *world.Tx) item.BoneMealResult {
if p.Growth == 7 {
return false
return item.BoneMealResultNone
}
p.Growth = min(p.Growth+rand.IntN(4)+2, 7)
tx.SetBlock(pos, p, nil)
return true
return item.BoneMealResultSmall
}

// UseOnBlock ...
Expand Down
Loading
Loading