Files
TarnaWijaya 26ed99fda6
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
up3
2026-07-09 08:33:57 +08:00

105 lines
3.0 KiB
Go

package entity
import (
"github.com/df-mc/dragonfly/server/block"
"github.com/df-mc/dragonfly/server/world"
"github.com/go-gl/mathgl/mgl64"
"math"
"time"
)
// PassiveBehaviourConfig holds optional parameters for a PassiveBehaviour.
type PassiveBehaviourConfig struct {
// Gravity is the amount of Y velocity subtracted every tick.
Gravity float64
// Drag is used to reduce all axes of the velocity every tick. Velocity is
// multiplied with (1-Drag) every tick.
Drag float64
// ExistenceDuration is the duration that an entity with this behaviour
// should last. Once this time expires, the entity is closed. If
// ExistenceDuration is 0, the entity will never expire automatically.
ExistenceDuration time.Duration
// Expire is called when the entity expires due to its age reaching the
// ExistenceDuration.
Expire func(e *Ent, tx *world.Tx)
// Tick is called for every tick that the entity is alive. Tick is called
// after the entity moves on a tick.
Tick func(e *Ent, tx *world.Tx)
}
func (conf PassiveBehaviourConfig) Apply(data *world.EntityData) {
data.Data = conf.New()
}
// New creates a PassiveBehaviour using the parameters in conf.
func (conf PassiveBehaviourConfig) New() *PassiveBehaviour {
if conf.ExistenceDuration == 0 {
conf.ExistenceDuration = math.MaxInt64
}
return &PassiveBehaviour{conf: conf, fuse: conf.ExistenceDuration, mc: &MovementComputer{
Gravity: conf.Gravity,
Drag: conf.Drag,
DragBeforeGravity: true,
}}
}
// PassiveBehaviour implements Behaviour for entities that act passively. This
// means that they can move, but only under influence of the environment, which
// includes, for example, falling, and flowing water.
type PassiveBehaviour struct {
conf PassiveBehaviourConfig
mc *MovementComputer
close bool
fallDistance float64
fuse time.Duration
}
// Explode adds velocity to a passive entity to blast it away from the
// explosion's source.
func (p *PassiveBehaviour) Explode(e *Ent, src mgl64.Vec3, impact float64, _ block.ExplosionConfig) {
e.data.Vel = e.data.Vel.Add(e.data.Pos.Sub(src).Normalize().Mul(impact))
}
// Fuse returns the leftover time until PassiveBehaviourConfig.Expire is called,
// or -1 if this function is not set.
func (p *PassiveBehaviour) Fuse() time.Duration {
if p.conf.Expire != nil {
return p.fuse
}
return -1
}
// Tick implements the behaviour for a passive entity. It performs movement and
// updates its state.
func (p *PassiveBehaviour) Tick(e *Ent, tx *world.Tx) *Movement {
if p.close {
_ = e.Close()
return nil
}
m := p.mc.TickMovement(e, e.data.Pos, e.data.Vel, e.data.Rot, tx)
e.data.Pos, e.data.Vel = m.pos, m.vel
p.fallDistance = math.Max(p.fallDistance-m.dvel[1], 0)
p.fuse = p.conf.ExistenceDuration - e.Age()
if p.conf.Tick != nil {
p.conf.Tick(e, tx)
}
if p.Fuse()%(time.Second/4) == 0 {
for _, v := range tx.Viewers(m.pos) {
v.ViewEntityState(e)
}
}
if e.Age() > p.conf.ExistenceDuration {
p.close = true
if p.conf.Expire != nil {
p.conf.Expire(e, tx)
}
}
return m
}