Skip to content

Commit

Permalink
world/entity.go: EntityData: Unexport pos and rot.
Browse files Browse the repository at this point in the history
  • Loading branch information
Sandertv committed Jan 9, 2025
1 parent 9e05eee commit 45fdd5d
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 69 deletions.
12 changes: 6 additions & 6 deletions server/entity/ent.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,24 +51,24 @@ func (e *Ent) Explode(src mgl64.Vec3, impact float64, conf block.ExplosionConfig

// Position returns the current position of the entity.
func (e *Ent) Position() mgl64.Vec3 {
return e.data.Pos
return e.data.Position()
}

// Velocity returns the current velocity of the entity. The values in the Vec3 returned represent the speed on
// that axis in blocks/tick.
func (e *Ent) Velocity() mgl64.Vec3 {
return e.data.Vel
return e.data.Velocity()
}

// 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.Vel = v
e.data.SetVelocity(e, e.tx, v)
}

// Rotation returns the rotation of the entity.
func (e *Ent) Rotation() cube.Rotation {
return e.data.Rot
return e.data.Rotation()
}

// Age returns the total time lived of this entity. It increases by
Expand All @@ -89,7 +89,7 @@ func (e *Ent) SetOnFire(duration time.Duration) {

e.data.FireDuration = duration
if stateChanged {
for _, v := range e.tx.Viewers(e.data.Pos) {
for _, v := range e.tx.Viewers(e.data.Position()) {
v.ViewEntityState(e)
}
}
Expand Down Expand Up @@ -118,7 +118,7 @@ func (e *Ent) SetNameTag(s string) {
// Tick ticks Ent, progressing its lifetime and closing the entity if it is
// in the void.
func (e *Ent) Tick(tx *world.Tx, current int64) {
y := e.data.Pos[1]
y := e.data.Position()[1]
if y < float64(tx.Range()[0]) && current%10 == 0 {
_ = e.Close()
return
Expand Down
13 changes: 8 additions & 5 deletions server/entity/firework_behaviour.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,20 @@ func (f *FireworkBehaviour) tick(e *Ent, tx *world.Tx) {
ownerVel = o.Velocity()
}

vel := e.data.Velocity()
if f.conf.Attached && ok {
dV := owner.Rotation().Vec3()

// The client will propel itself to match the firework's velocity since
// we set the appropriate metadata.
e.data.Pos = owner.Position()
e.data.Vel = e.data.Vel.Add(ownerVel.Add(dV.Mul(0.1).Add(dV.Mul(1.5).Sub(ownerVel).Mul(0.5))))
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)))))
} else {
e.data.Vel[0] *= f.conf.SidewaysVelocityMultiplier
e.data.Vel[1] += f.conf.UpwardsAcceleration
e.data.Vel[2] *= f.conf.SidewaysVelocityMultiplier
e.data.SetVelocity(e, tx, mgl64.Vec3{
vel[0] * f.conf.SidewaysVelocityMultiplier,
vel[1] * f.conf.UpwardsAcceleration,

This comment has been minimized.

Copy link
@DaPigGuy

DaPigGuy Jan 10, 2025

Member

Should be +

vel[2] * f.conf.SidewaysVelocityMultiplier,
})
}
}

Expand Down
7 changes: 4 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.Vel = e.data.Vel.Add(e.data.Pos.Sub(src).Normalize().Mul(impact))
e.data.SetVelocity(e, e.tx, e.data.Velocity().Add(e.data.Position().Sub(src).Normalize().Mul(impact)))
}

// Fuse returns the leftover time until PassiveBehaviourConfig.Expire is called,
Expand All @@ -78,8 +78,9 @@ func (p *PassiveBehaviour) Tick(e *Ent, tx *world.Tx) *Movement {
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
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)
p.fallDistance = math.Max(p.fallDistance-m.dvel[1], 0)

p.fuse = p.conf.ExistenceDuration - e.Age()
Expand Down
5 changes: 3 additions & 2 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.Vel = e.Velocity().Add(e.Position().Sub(src).Normalize().Mul(impact))
e.data.SetVelocity(e, e.tx, 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,7 +150,8 @@ func (lt *ProjectileBehaviour) Tick(e *Ent, tx *world.Tx) *Movement {
}
vel := e.Velocity()
m, result := lt.tickMovement(e, tx)
e.data.Pos, e.data.Vel = m.pos, m.vel
e.data.Move(e, tx, m.pos, m.rot, m.onGround)
e.data.SetVelocity(e, tx, m.vel)

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

Expand Down
1 change: 0 additions & 1 deletion server/player/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ type Config struct {
func (cfg Config) Apply(data *world.EntityData) {
conf := fillDefaults(cfg)

data.Name, data.Pos, data.Rot = conf.Name, conf.Position, conf.Rotation
slot := uint32(conf.HeldSlot)
pdata := &playerData{
xuid: conf.XUID,
Expand Down
31 changes: 8 additions & 23 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.Pos = p.tx.World().Spawn().Vec3()
p.data.Move(p, p.tx, p.tx.World().Spawn().Vec3(), p.Rotation(), p.onGround)
}
}

Expand Down Expand Up @@ -2032,11 +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) {
for _, v := range p.viewers() {
v.ViewEntityTeleport(p, pos)
}
p.data.Pos = pos
p.data.Vel = mgl64.Vec3{}
p.data.Teleport(p, p.tx, pos)
p.ResetFallDistance()
}

Expand Down Expand Up @@ -2068,12 +2064,7 @@ func (p *Player) Move(deltaPos mgl64.Vec3, deltaYaw, deltaPitch float64) {
}
return
}
for _, v := range p.viewers() {
v.ViewEntityMovement(p, res, resRot, p.OnGround())
}

p.data.Pos = res
p.data.Rot = resRot
p.data.Move(p, p.tx, 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 @@ -2115,31 +2106,25 @@ func (p *Player) Move(deltaPos mgl64.Vec3, deltaYaw, deltaPitch float64) {
// Position returns the current position of the player. It may be changed as the player moves or is moved
// around the world.
func (p *Player) Position() mgl64.Vec3 {
return p.data.Pos
return p.data.Position()
}

// Velocity returns the players current velocity. If there is an attached session, this will be empty.
func (p *Player) Velocity() mgl64.Vec3 {
return p.data.Vel
return p.data.Velocity()
}

// 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) {
if p.session() == session.Nop {
p.data.Vel = velocity
return
}
for _, v := range p.viewers() {
v.ViewEntityVelocity(p, velocity)
}
p.data.SetVelocity(p, p.tx, velocity)
}

// Rotation returns the yaw and pitch of the player in degrees. Yaw is horizontal rotation (rotation around the
// vertical axis, 0 when facing forward), pitch is vertical rotation (rotation around the horizontal axis, also 0
// when facing forward).
func (p *Player) Rotation() cube.Rotation {
return p.data.Rot
return p.data.Rotation()
}

// Collect makes the player collect the item stack passed, adding it to the inventory. The amount of items that could
Expand Down Expand Up @@ -2352,7 +2337,7 @@ func (p *Player) Tick(tx *world.Tx, current int64) {
}
}

p.checkBlockCollisions(p.data.Vel)
p.checkBlockCollisions(p.data.Velocity())
p.onGround = p.checkOnGround()

p.effects.Tick(p, p.tx)
Expand Down
8 changes: 7 additions & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,13 @@ func (srv *Server) createPlayer(id uuid.UUID, conn session.Conn, conf player.Con
conf.Skin = srv.parseSkin(conn.ClientData())
conf.Session = s

handle := world.EntitySpawnOpts{Position: conf.Position, ID: id}.New(player.Type, conf)
handle := world.EntitySpawnOpts{
NameTag: conf.Name,
Position: conf.Position,
Rotation: conf.Rotation,
Velocity: conf.Velocity,
ID: id,
}.New(player.Type, conf)
s.SetHandle(handle, conf.Skin)
return incoming{s: s, w: w, conf: conf, p: &onlinePlayer{name: conf.Name, xuid: conf.XUID, handle: handle}}
}
Expand Down
72 changes: 46 additions & 26 deletions server/world/entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ func (opts EntitySpawnOpts) New(t EntityType, conf EntityConfig) *EntityHandle {
}
handle := &EntityHandle{id: opts.ID, t: t, cond: sync.NewCond(&sync.Mutex{}), worldless: &atomic.Bool{}}
handle.worldless.Store(true)
handle.data.Pos, handle.data.Rot, handle.data.Vel = opts.Position, opts.Rotation, opts.Velocity
handle.data.pos, handle.data.rot, handle.data.Vel = opts.Position, opts.Rotation, opts.Velocity
handle.data.Name = opts.NameTag
conf.Apply(&handle.data)
return handle
Expand Down Expand Up @@ -265,9 +265,9 @@ func (e *EntityHandle) setAndUnlockWorld(w *World) {
// decodeNBT decodes the position, velocity, rotation, age, on-fire duration and
// name tag of an entity.
func (e *EntityHandle) decodeNBT(m map[string]any) {
e.data.Pos = readVec3(m, "Pos")
e.data.pos = readVec3(m, "Pos")
e.data.Vel = readVec3(m, "Motion")
e.data.Rot = readRotation(m)
e.data.rot = readRotation(m)
e.data.Age = time.Duration(readInt16(m, "Age")) * (time.Second / 20)
e.data.FireDuration = time.Duration(readInt16(m, "Fire")) * time.Second / 20
e.data.Name, _ = m["NameTag"].(string)
Expand All @@ -277,10 +277,10 @@ func (e *EntityHandle) decodeNBT(m map[string]any) {
// name tag of an entity.
func (e *EntityHandle) encodeNBT() map[string]any {
return map[string]any{
"Pos": []float32{float32(e.data.Pos[0]), float32(e.data.Pos[1]), float32(e.data.Pos[2])},
"Pos": []float32{float32(e.data.pos[0]), float32(e.data.pos[1]), float32(e.data.pos[2])},
"Motion": []float32{float32(e.data.Vel[0]), float32(e.data.Vel[1]), float32(e.data.Vel[2])},
"Yaw": float32(e.data.Rot[0]),
"Pitch": float32(e.data.Rot[1]),
"Yaw": float32(e.data.rot[0]),
"Pitch": float32(e.data.rot[1]),
"Fire": int16(e.data.FireDuration.Seconds() * 20),
"Age": int16(e.data.Age / (time.Second * 20)),
"NameTag": e.data.Name,
Expand All @@ -289,28 +289,62 @@ func (e *EntityHandle) encodeNBT() map[string]any {

// EntityData holds data shared by every entity. It is kept in an EntityHandle.
type EntityData struct {
Pos, Vel mgl64.Vec3
Rot cube.Rotation
pos, Vel mgl64.Vec3
rot cube.Rotation
Name string
FireDuration time.Duration
Age time.Duration

Data any
}

func (edata *EntityData) Velocity() mgl64.Vec3 {
return edata.Vel
}

func (edata *EntityData) SetVelocity(e Entity, tx *Tx, 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) {
for _, v := range tx.Viewers(edata.pos) {
v.ViewEntityVelocity(e, vel)
}
}
edata.Vel = vel
}

func (edata *EntityData) Position() mgl64.Vec3 {
return edata.pos
}

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)
}
edata.setPosition(e, tx, 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) {
prevChunkPos, chunkPos := chunkPosFromVec3(edata.Pos), chunkPosFromVec3(pos)
edata.updatePosition(e, tx, pos, rot, onGround)
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)
}
}
edata.setPosition(e, tx, pos, rot)
}

func (edata *EntityData) setPosition(e Entity, tx *Tx, pos mgl64.Vec3, rot cube.Rotation) {
prevChunkPos, chunkPos := chunkPosFromVec3(edata.pos), chunkPosFromVec3(pos)
if prevChunkPos == chunkPos {
// Entity remains in the same chunk.
return
Expand All @@ -330,6 +364,7 @@ func (edata *EntityData) Move(e Entity, tx *Tx, pos mgl64.Vec3, rot cube.Rotatio
viewer.HideEntity(e)
}
}
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
Expand All @@ -339,21 +374,6 @@ func (edata *EntityData) Move(e Entity, tx *Tx, pos mgl64.Vec3, rot cube.Rotatio
}
}

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

func (edata *EntityData) updatePosition(e Entity, tx *Tx, 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)
}
}
edata.Pos, edata.Rot = pos, rot
}

// Entity represents an Entity in the world, typically an object that may be moved around and can be
// interacted with by other entities.
// Viewers of a world may view an Entity when near it.
Expand Down
4 changes: 2 additions & 2 deletions server/world/world.go
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ func (w *World) playSound(tx *Tx, pos mgl64.Vec3, s Sound) {
// addEntity returns the Entity created by the EntityHandle.
func (w *World) addEntity(tx *Tx, handle *EntityHandle) Entity {
handle.setAndUnlockWorld(w)
pos := chunkPosFromVec3(handle.data.Pos)
pos := chunkPosFromVec3(handle.data.pos)
w.entities[handle] = struct{}{}

c := w.chunk(pos)
Expand Down Expand Up @@ -713,7 +713,7 @@ func (w *World) entitiesWithin(tx *Tx, box cube.BBox) iter.Seq[Entity] {
continue
}
for _, handle := range c.Entities {
if !box.Vec3Within(handle.data.Pos) {
if !box.Vec3Within(handle.data.pos) {
continue
}
if !yield(handle.mustEntity(tx)) {
Expand Down

0 comments on commit 45fdd5d

Please sign in to comment.