Skip to content

Commit

Permalink
entity/tnt.go: Add context for the entity that ignited the tnt (#848)
Browse files Browse the repository at this point in the history
  • Loading branch information
RestartFU authored Mar 6, 2024
1 parent 6aea938 commit 0fc276f
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 21 deletions.
2 changes: 1 addition & 1 deletion server/block/fire.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func (f Fire) burn(from, to cube.Pos, w *world.World, r *rand.Rand, chanceBound
return
}
if t, ok := flammable.(TNT); ok {
t.Ignite(to, w)
t.Ignite(to, w, nil)
return
}
w.SetBlock(to, nil, nil)
Expand Down
20 changes: 14 additions & 6 deletions server/block/tnt.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,36 @@ import (
// TNT is an explosive block that can be primed to generate an explosion.
type TNT struct {
solid
igniter world.Entity
}

// Activate ...
func (t TNT) Activate(pos cube.Pos, _ cube.Face, w *world.World, u item.User, ctx *item.UseContext) bool {
held, _ := u.HeldItems()
if _, ok := held.Enchantment(enchantment.FireAspect{}); ok {
t.Ignite(pos, w)
t.Ignite(pos, w, u)
ctx.DamageItem(1)
return true
}
return false
}

// Ignite ...
func (t TNT) Ignite(pos cube.Pos, w *world.World) bool {
spawnTnt(pos, w, time.Second*4)
func (t TNT) Ignite(pos cube.Pos, w *world.World, igniter world.Entity) bool {
t.igniter = igniter
spawnTnt(pos, w, time.Second*4, t.igniter)
return true
}

// Igniter returns the entity that ignited the TNT.
// It is nil if ignited by a world source like fire.
func (t TNT) Igniter() world.Entity {
return t.igniter
}

// Explode ...
func (t TNT) Explode(_ mgl64.Vec3, pos cube.Pos, w *world.World, _ ExplosionConfig) {
spawnTnt(pos, w, time.Second/2+time.Duration(rand.Intn(int(time.Second+time.Second/2))))
spawnTnt(pos, w, time.Second/2+time.Duration(rand.Intn(int(time.Second+time.Second/2))), t.igniter)
}

// BreakInfo ...
Expand All @@ -59,8 +67,8 @@ func (t TNT) EncodeBlock() (name string, properties map[string]interface{}) {
}

// spawnTnt creates a new TNT entity at the given position with the given fuse duration.
func spawnTnt(pos cube.Pos, w *world.World, fuse time.Duration) {
func spawnTnt(pos cube.Pos, w *world.World, fuse time.Duration, igniter world.Entity) {
w.PlaySound(pos.Vec3Centre(), sound.TNT{})
w.SetBlock(pos, nil, nil)
w.AddEntity(w.EntityRegistry().Config().TNT(pos.Vec3Centre(), fuse))
w.AddEntity(w.EntityRegistry().Config().TNT(pos.Vec3Centre(), fuse, igniter))
}
2 changes: 1 addition & 1 deletion server/entity/projectile.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func (lt *ProjectileBehaviour) Tick(e *Ent) *Movement {
case trace.BlockResult:
bpos := r.BlockPosition()
if t, ok := w.Block(bpos).(block.TNT); ok && e.OnFireDuration() > 0 {
t.Ignite(bpos, w)
t.Ignite(bpos, w, e)
}
if lt.conf.SurviveBlockCollision {
lt.hitBlockSurviving(e, r, m)
Expand Down
4 changes: 2 additions & 2 deletions server/entity/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ var conf = world.EntityRegistryConfig{
FallingBlock: func(bl world.Block, pos mgl64.Vec3) world.Entity {
return NewFallingBlock(bl, pos)
},
TNT: func(pos mgl64.Vec3, fuse time.Duration) world.Entity {
return NewTNT(pos, fuse)
TNT: func(pos mgl64.Vec3, fuse time.Duration, igniter world.Entity) world.Entity {
return NewTNT(pos, fuse, igniter)
},
BottleOfEnchanting: func(pos, vel mgl64.Vec3, owner world.Entity) world.Entity {
b := NewBottleOfEnchanting(pos, owner)
Expand Down
16 changes: 11 additions & 5 deletions server/entity/tnt.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ import (
)

// NewTNT creates a new primed TNT entity.
func NewTNT(pos mgl64.Vec3, fuse time.Duration) *Ent {
func NewTNT(pos mgl64.Vec3, fuse time.Duration, igniter world.Entity) *Ent {
config := tntConf
config.ExistenceDuration = fuse
ent := Config{Behaviour: config.New()}.New(TNTType{}, pos)
ent := Config{Behaviour: config.New()}.New(TNTType{igniter: igniter}, pos)

angle := rand.Float64() * math.Pi * 2
ent.vel = mgl64.Vec3{-math.Sin(angle) * 0.02, 0.1, -math.Cos(angle) * 0.02}
Expand All @@ -35,16 +35,22 @@ func explodeTNT(e *Ent) {
}

// TNTType is a world.EntityType implementation for TNT.
type TNTType struct{}
type TNTType struct {
igniter world.Entity
}

// Igniter returns the entity that ignited the TNT.
// It is nil if ignited by a world source like fire.
func (t TNTType) Igniter() world.Entity { return t.igniter }

func (TNTType) EncodeEntity() string { return "minecraft:tnt" }
func (TNTType) NetworkOffset() float64 { return 0.49 }
func (TNTType) BBox(world.Entity) cube.BBox {
return cube.Box(-0.49, 0, -0.49, 0.49, 0.98, 0.49)
}

func (TNTType) DecodeNBT(m map[string]any) world.Entity {
tnt := NewTNT(nbtconv.Vec3(m, "Pos"), nbtconv.TickDuration[uint8](m, "Fuse"))
func (t TNTType) DecodeNBT(m map[string]any) world.Entity {
tnt := NewTNT(nbtconv.Vec3(m, "Pos"), nbtconv.TickDuration[uint8](m, "Fuse"), t.igniter)
tnt.vel = nbtconv.Vec3(m, "Motion")
return tnt
}
Expand Down
4 changes: 2 additions & 2 deletions server/item/fire_charge.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ func (f FireCharge) EncodeItem() (name string, meta int16) {
}

// UseOnBlock ...
func (f FireCharge) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, _ User, ctx *UseContext) bool {
if l, ok := w.Block(pos).(ignitable); ok && l.Ignite(pos, w) {
func (f FireCharge) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, u User, ctx *UseContext) bool {
if l, ok := w.Block(pos).(ignitable); ok && l.Ignite(pos, w, u) {
ctx.SubtractFromCount(1)
w.PlaySound(pos.Vec3Centre(), sound.FireCharge{})
return true
Expand Down
6 changes: 3 additions & 3 deletions server/item/flint_and_steel.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ func (f FlintAndSteel) DurabilityInfo() DurabilityInfo {
// ignitable represents a block that can be lit by a fire emitter, such as flint and steel.
type ignitable interface {
// Ignite is called when the block is lit by flint and steel.
Ignite(pos cube.Pos, w *world.World) bool
Ignite(pos cube.Pos, w *world.World, igniter world.Entity) bool
}

// UseOnBlock ...
func (f FlintAndSteel) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, _ User, ctx *UseContext) bool {
func (f FlintAndSteel) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, u User, ctx *UseContext) bool {
ctx.DamageItem(1)
if l, ok := w.Block(pos).(ignitable); ok && l.Ignite(pos, w) {
if l, ok := w.Block(pos).(ignitable); ok && l.Ignite(pos, w, u) {
return true
} else if s := pos.Side(face); w.Block(s) == air() {
w.PlaySound(s.Vec3Centre(), sound.Ignite{})
Expand Down
2 changes: 1 addition & 1 deletion server/world/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ type EntityRegistry struct {
type EntityRegistryConfig struct {
Item func(it any, pos, vel mgl64.Vec3) Entity
FallingBlock func(bl Block, pos mgl64.Vec3) Entity
TNT func(pos mgl64.Vec3, fuse time.Duration) Entity
TNT func(pos mgl64.Vec3, fuse time.Duration, igniter Entity) Entity
BottleOfEnchanting func(pos, vel mgl64.Vec3, owner Entity) Entity
Arrow func(pos, vel mgl64.Vec3, rot cube.Rotation, damage float64, owner Entity, critical, disallowPickup, obtainArrowOnPickup bool, punchLevel int, tip any) Entity
Egg func(pos, vel mgl64.Vec3, owner Entity) Entity
Expand Down

0 comments on commit 0fc276f

Please sign in to comment.