Skip to content

Commit

Permalink
world/entity.go: EntityData: Embed tx and entity into data to avoid h…
Browse files Browse the repository at this point in the history
…aving to pass them everytime.
  • Loading branch information
Sandertv committed Jan 9, 2025
1 parent 45fdd5d commit 6822ee3
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 43 deletions.
6 changes: 3 additions & 3 deletions server/entity/ent.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (e *Ent) Velocity() mgl64.Vec3 {
// SetVelocity sets the velocity of the entity. The values in the Vec3 passed represent the speed on
// that axis in blocks/tick.
func (e *Ent) SetVelocity(v mgl64.Vec3) {
e.data.SetVelocity(e, e.tx, v)
e.data.SetVelocity(v)
}

// Rotation returns the rotation of the entity.
Expand Down Expand Up @@ -126,8 +126,8 @@ func (e *Ent) Tick(tx *world.Tx, current int64) {
e.SetOnFire(e.OnFireDuration() - time.Second/20)

if m := e.Behaviour().Tick(e, tx); m != nil {
e.data.Move(e, tx, m.pos, m.rot, m.onGround)
e.data.SetVelocity(e, tx, m.vel)
e.data.Move(m.pos, m.rot, m.onGround)
e.data.SetVelocity(m.vel)
}
e.data.Age += time.Second / 20
}
Expand Down
6 changes: 3 additions & 3 deletions server/entity/firework_behaviour.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ func (f *FireworkBehaviour) tick(e *Ent, tx *world.Tx) {

// The client will propel itself to match the firework's velocity since
// we set the appropriate metadata.
e.data.Move(e, tx, owner.Position(), e.data.Rotation(), false)
e.data.SetVelocity(e, tx, vel.Add(ownerVel.Add(dV.Mul(0.1).Add(dV.Mul(1.5).Sub(ownerVel).Mul(0.5)))))
e.data.Move(owner.Position(), e.data.Rotation(), false)
e.data.SetVelocity(vel.Add(ownerVel.Add(dV.Mul(0.1).Add(dV.Mul(1.5).Sub(ownerVel).Mul(0.5)))))
} else {
e.data.SetVelocity(e, tx, mgl64.Vec3{
e.data.SetVelocity(mgl64.Vec3{
vel[0] * f.conf.SidewaysVelocityMultiplier,
vel[1] * f.conf.UpwardsAcceleration,
vel[2] * f.conf.SidewaysVelocityMultiplier,
Expand Down
6 changes: 3 additions & 3 deletions server/entity/passive.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ type PassiveBehaviour struct {
// 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.SetVelocity(e, e.tx, e.data.Velocity().Add(e.data.Position().Sub(src).Normalize().Mul(impact)))
e.data.SetVelocity(e.data.Velocity().Add(e.data.Position().Sub(src).Normalize().Mul(impact)))
}

// Fuse returns the leftover time until PassiveBehaviourConfig.Expire is called,
Expand All @@ -79,8 +79,8 @@ func (p *PassiveBehaviour) Tick(e *Ent, tx *world.Tx) *Movement {
}

m := p.mc.TickMovement(e, e.data.Position(), e.data.Velocity(), e.data.Rotation(), tx)
e.data.Move(e, tx, m.pos, m.rot, m.onGround)
e.data.SetVelocity(e, tx, m.vel)
e.data.Move(m.pos, m.rot, m.onGround)
e.data.SetVelocity(m.vel)
p.fallDistance = math.Max(p.fallDistance-m.dvel[1], 0)

p.fuse = p.conf.ExistenceDuration - e.Age()
Expand Down
6 changes: 3 additions & 3 deletions server/entity/projectile.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func (lt *ProjectileBehaviour) Owner() *world.EntityHandle {
// Explode adds velocity to a projectile to blast it away from the explosion's
// source.
func (lt *ProjectileBehaviour) Explode(e *Ent, src mgl64.Vec3, impact float64, _ block.ExplosionConfig) {
e.data.SetVelocity(e, e.tx, e.Velocity().Add(e.Position().Sub(src).Normalize().Mul(impact)))
e.data.SetVelocity(e.Velocity().Add(e.Position().Sub(src).Normalize().Mul(impact)))
}

// Potion returns the potion.Potion that is applied to an entity if hit by the
Expand Down Expand Up @@ -150,8 +150,8 @@ func (lt *ProjectileBehaviour) Tick(e *Ent, tx *world.Tx) *Movement {
}
vel := e.Velocity()
m, result := lt.tickMovement(e, tx)
e.data.Move(e, tx, m.pos, m.rot, m.onGround)
e.data.SetVelocity(e, tx, m.vel)
e.data.Move(m.pos, m.rot, m.onGround)
e.data.SetVelocity(m.vel)

lt.collisionPos, lt.collided, lt.ageCollided = cube.Pos{}, false, 0

Expand Down
12 changes: 6 additions & 6 deletions server/player/player.go
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ func finishDying(_ *world.Tx, e world.Entity) {
// position server side so that in the future, the client won't respawn
// on the death location when disconnecting. The client should not see
// the movement itself yet, though.
p.data.Move(p, p.tx, p.tx.World().Spawn().Vec3(), p.Rotation(), p.onGround)
p.data.Move(p.tx.World().Spawn().Vec3(), p.Rotation(), p.onGround)
}
}

Expand Down Expand Up @@ -2032,7 +2032,7 @@ func (p *Player) Teleport(pos mgl64.Vec3) {
// teleport teleports the player to a target position in the world. It does not call the Handler of the
// player.
func (p *Player) teleport(pos mgl64.Vec3) {
p.data.Teleport(p, p.tx, pos)
p.data.Teleport(pos)
p.ResetFallDistance()
}

Expand Down Expand Up @@ -2064,7 +2064,7 @@ func (p *Player) Move(deltaPos mgl64.Vec3, deltaYaw, deltaPitch float64) {
}
return
}
p.data.Move(p, p.tx, res, resRot, p.OnGround())
p.data.Move(res, resRot, p.OnGround())
if deltaPos.Len() <= 3 {
// Only update velocity if the player is not moving too fast to prevent potential OOMs.
p.data.Vel = deltaPos
Expand Down Expand Up @@ -2117,7 +2117,7 @@ func (p *Player) Velocity() mgl64.Vec3 {
// SetVelocity updates the player's velocity. If there is an attached session, this will just send
// the velocity to the player session for the player to update.
func (p *Player) SetVelocity(velocity mgl64.Vec3) {
p.data.SetVelocity(p, p.tx, velocity)
p.data.SetVelocity(velocity)
}

// Rotation returns the yaw and pitch of the player in degrees. Yaw is horizontal rotation (rotation around the
Expand Down Expand Up @@ -2397,8 +2397,8 @@ func (p *Player) Tick(tx *world.Tx, current int64) {

// TODO: Move p.data.Move into p.Move()
// p.Move(m.Position().Sub(p.Position()), 0, 0)
p.data.Move(p, tx, m.Position(), m.Rotation(), p.onGround)
p.data.SetVelocity(p, tx, m.Velocity())
p.data.Move(m.Position(), m.Rotation(), p.onGround)
p.data.SetVelocity(m.Velocity())
} else {
p.data.Vel = mgl64.Vec3{}
}
Expand Down
52 changes: 28 additions & 24 deletions server/world/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type EntityHandle struct {
weakTxActive bool
w *World

data EntityData
data *EntityData

// TODO Handler? Handle world change here?
}
Expand Down Expand Up @@ -83,11 +83,11 @@ func (opts EntitySpawnOpts) New(t EntityType, conf EntityConfig) *EntityHandle {
opts.ID = uuid.New()
clear(opts.ID[:8])
}
handle := &EntityHandle{id: opts.ID, t: t, cond: sync.NewCond(&sync.Mutex{}), worldless: &atomic.Bool{}}
handle := &EntityHandle{id: opts.ID, t: t, cond: sync.NewCond(&sync.Mutex{}), worldless: &atomic.Bool{}, data: &EntityData{}}
handle.worldless.Store(true)
handle.data.pos, handle.data.rot, handle.data.Vel = opts.Position, opts.Rotation, opts.Velocity
handle.data.Name = opts.NameTag
conf.Apply(&handle.data)
conf.Apply(handle.data)
return handle
}

Expand All @@ -102,10 +102,10 @@ func NewEntity(t EntityType, conf EntityConfig) *EntityHandle {
// entityFromData reads an entity from the decoded NBT data passed and returns
// an EntityHandle.
func entityFromData(t EntityType, id int64, data map[string]any) *EntityHandle {
handle := &EntityHandle{t: t, cond: sync.NewCond(&sync.Mutex{}), worldless: &atomic.Bool{}}
handle := &EntityHandle{t: t, cond: sync.NewCond(&sync.Mutex{}), worldless: &atomic.Bool{}, data: &EntityData{}}
binary.LittleEndian.PutUint64(handle.id[8:], uint64(id))
handle.decodeNBT(data)
t.DecodeNBT(data, &handle.data)
t.DecodeNBT(data, handle.data)
return handle
}

Expand All @@ -121,7 +121,8 @@ func (e *EntityHandle) Entity(tx *Tx) (Entity, bool) {
if e == nil || e.w != tx.World() {
return nil, false
}
return e.t.Open(tx, e, &e.data), true
e.data.ent, e.data.tx = e.t.Open(tx, e, e.data), tx
return e.data.ent, true
}

// mustEntity calls Entity but panics if the worlds do not match.
Expand Down Expand Up @@ -289,6 +290,9 @@ func (e *EntityHandle) encodeNBT() map[string]any {

// EntityData holds data shared by every entity. It is kept in an EntityHandle.
type EntityData struct {
ent Entity
tx *Tx

pos, Vel mgl64.Vec3
rot cube.Rotation
Name string
Expand All @@ -302,11 +306,11 @@ func (edata *EntityData) Velocity() mgl64.Vec3 {
return edata.Vel
}

func (edata *EntityData) SetVelocity(e Entity, tx *Tx, vel mgl64.Vec3) {
func (edata *EntityData) SetVelocity(vel mgl64.Vec3) {
if !vel.ApproxEqualThreshold(edata.Vel, epsilon) {
// Only send velocity if the delta is big enough.
for _, v := range tx.Viewers(edata.pos) {
v.ViewEntityVelocity(e, vel)
for _, v := range edata.tx.Viewers(edata.pos) {
v.ViewEntityVelocity(edata.ent, vel)
}
}
edata.Vel = vel
Expand All @@ -320,30 +324,30 @@ func (edata *EntityData) Rotation() cube.Rotation {
return edata.rot
}

func (edata *EntityData) Teleport(e Entity, tx *Tx, pos mgl64.Vec3) {
edata.SetVelocity(e, tx, mgl64.Vec3{})
for _, v := range tx.Viewers(edata.pos) {
v.ViewEntityTeleport(e, pos)
func (edata *EntityData) Teleport(pos mgl64.Vec3) {
edata.SetVelocity(mgl64.Vec3{})
for _, v := range edata.tx.Viewers(edata.pos) {
v.ViewEntityTeleport(edata.ent, pos)
}
edata.setPosition(e, tx, pos, edata.rot)
edata.setPosition(pos, edata.rot)
}

// epsilon is the epsilon used for thresholds for change used for change in
// position and velocity.
const epsilon = 0.001

func (edata *EntityData) Move(e Entity, tx *Tx, pos mgl64.Vec3, rot cube.Rotation, onGround bool) {
func (edata *EntityData) Move(pos mgl64.Vec3, rot cube.Rotation, onGround bool) {
if !pos.ApproxEqualThreshold(edata.pos, epsilon) || !mgl64.Vec2(rot).ApproxEqualThreshold(mgl64.Vec2(edata.rot), epsilon) {
// Only send movement if the delta of either rotation or position is
// significant enough.
for _, v := range tx.Viewers(edata.pos) {
v.ViewEntityMovement(e, pos, rot, onGround)
for _, v := range edata.tx.Viewers(edata.pos) {
v.ViewEntityMovement(edata.ent, pos, rot, onGround)
}
}
edata.setPosition(e, tx, pos, rot)
edata.setPosition(pos, rot)
}

func (edata *EntityData) setPosition(e Entity, tx *Tx, pos mgl64.Vec3, rot cube.Rotation) {
func (edata *EntityData) setPosition(pos mgl64.Vec3, rot cube.Rotation) {
prevChunkPos, chunkPos := chunkPosFromVec3(edata.pos), chunkPosFromVec3(pos)
if prevChunkPos == chunkPos {
// Entity remains in the same chunk.
Expand All @@ -352,24 +356,24 @@ func (edata *EntityData) setPosition(e Entity, tx *Tx, pos mgl64.Vec3, rot cube.

// The entity's chunk position changed: Move it from the old chunk to the
// new chunk.
prevChunk, chunk := tx.World().chunk(prevChunkPos), tx.World().chunk(chunkPos)
prevChunk, chunk := edata.tx.World().chunk(prevChunkPos), edata.tx.World().chunk(chunkPos)

chunk.Entities = append(chunk.Entities, e.H())
prevChunk.Entities = sliceutil.DeleteVal(prevChunk.Entities, e.H())
chunk.Entities = append(chunk.Entities, edata.ent.H())
prevChunk.Entities = sliceutil.DeleteVal(prevChunk.Entities, edata.ent.H())

for _, viewer := range prevChunk.viewers {
if slices.Index(chunk.viewers, viewer) == -1 {
// First we hide the entity from all viewers that were previously
// viewing it, but no longer are.
viewer.HideEntity(e)
viewer.HideEntity(edata.ent)
}
}
edata.pos, edata.rot = pos, rot
for _, viewer := range chunk.viewers {
if slices.Index(prevChunk.viewers, viewer) == -1 {
// Then we show the entity to all loaders that are now viewing the
// entity in the new chunk.
showEntity(e, viewer)
showEntity(edata.ent, viewer)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion server/world/world.go
Original file line number Diff line number Diff line change
Expand Up @@ -1240,7 +1240,7 @@ func (w *World) columnTo(col *Column, pos ChunkPos) *chunk.Column {
}
for _, e := range col.Entities {
data := e.encodeNBT()
maps.Copy(data, e.t.EncodeNBT(&e.data))
maps.Copy(data, e.t.EncodeNBT(e.data))
data["identifier"] = e.t.EncodeEntity()
c.Entities = append(c.Entities, chunk.Entity{ID: int64(binary.LittleEndian.Uint64(e.id[8:])), Data: data})
}
Expand Down

0 comments on commit 6822ee3

Please sign in to comment.