From fc8942cda833e4d4cfbf37be6aaabfa442b5f02c Mon Sep 17 00:00:00 2001 From: Hashim <13991048+Prim69@users.noreply.github.com> Date: Mon, 4 Jul 2022 00:58:25 -0400 Subject: [PATCH 01/10] e --- server/player/player.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/player/player.go b/server/player/player.go index 667d64b2c..f2958a958 100644 --- a/server/player/player.go +++ b/server/player/player.go @@ -529,7 +529,7 @@ func (p *Player) Hurt(dmg float64, source damage.Source) (float64, bool) { totalDamage := p.FinalDamageFrom(dmg, source) damageLeft := totalDamage - if a := p.absorption(); a > 0 { + if a := p.Absorption(); a > 0 { if damageLeft > a { damageLeft -= a p.SetAbsorption(0) @@ -598,7 +598,7 @@ func (p *Player) FinalDamageFrom(dmg float64, src damage.Source) float64 { return math.Max(dmg, 0) } -// SetAbsorption sets the absorption health of a player. This extra health shows as golden hearts and do not +// SetAbsorption sets the Absorption health of a player. This extra health shows as golden hearts and do not // actually increase the maximum health. Once the hearts are lost, they will not regenerate. // Nothing happens if a negative number is passed. func (p *Player) SetAbsorption(health float64) { @@ -607,8 +607,8 @@ func (p *Player) SetAbsorption(health float64) { p.session().SendAbsorption(health) } -// absorption returns the absorption health that the player has. -func (p *Player) absorption() float64 { +// Absorption returns the Absorption health that the player has. +func (p *Player) Absorption() float64 { return p.absorptionHealth.Load() } From 5db932282cc6e27a891878c05e7ef8e4c25cac61 Mon Sep 17 00:00:00 2001 From: Hashim <13991048+Prim69@users.noreply.github.com> Date: Mon, 4 Jul 2022 00:59:14 -0400 Subject: [PATCH 02/10] e 2 --- server/player/player.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/player/player.go b/server/player/player.go index f2958a958..cd6bca061 100644 --- a/server/player/player.go +++ b/server/player/player.go @@ -598,7 +598,7 @@ func (p *Player) FinalDamageFrom(dmg float64, src damage.Source) float64 { return math.Max(dmg, 0) } -// SetAbsorption sets the Absorption health of a player. This extra health shows as golden hearts and do not +// SetAbsorption sets the absorption health of a player. This extra health shows as golden hearts and do not // actually increase the maximum health. Once the hearts are lost, they will not regenerate. // Nothing happens if a negative number is passed. func (p *Player) SetAbsorption(health float64) { @@ -607,7 +607,7 @@ func (p *Player) SetAbsorption(health float64) { p.session().SendAbsorption(health) } -// Absorption returns the Absorption health that the player has. +// Absorption returns the absorption health that the player has. func (p *Player) Absorption() float64 { return p.absorptionHealth.Load() } From 3513f388f0fc90cce6f591e2503a2fff2d233a7b Mon Sep 17 00:00:00 2001 From: Hashim <13991048+Prim69@users.noreply.github.com> Date: Sun, 10 Jul 2022 02:23:50 -0400 Subject: [PATCH 03/10] pog --- server/entity/fall.go | 138 ++++++++++++++++++++++++++++++++++++++++ server/entity/living.go | 3 + server/player/player.go | 84 ++++-------------------- 3 files changed, 152 insertions(+), 73 deletions(-) create mode 100644 server/entity/fall.go diff --git a/server/entity/fall.go b/server/entity/fall.go new file mode 100644 index 000000000..59c4af3e4 --- /dev/null +++ b/server/entity/fall.go @@ -0,0 +1,138 @@ +package entity + +import ( + "github.com/df-mc/dragonfly/server/block/cube" + "github.com/df-mc/dragonfly/server/entity/damage" + "github.com/df-mc/dragonfly/server/entity/effect" + "github.com/df-mc/dragonfly/server/world" + "github.com/go-gl/mathgl/mgl64" + "math" + "sync" +) + +// FallManager handles entities that can fall. +type FallManager struct { + mu sync.Mutex + e fallEntity + fallDistance float64 + onGround bool +} + +// fallEntity is an entity that can fall. +type fallEntity interface { + world.Entity + OnGround() bool +} + +// entityLander represents a block that reacts to an entity landing on it after falling. +type entityLander interface { + // EntityLand is called when an entity lands on the block. + EntityLand(pos cube.Pos, w *world.World, e world.Entity) +} + +// NewFallManager returns a new fall manager. +func NewFallManager(e fallEntity) *FallManager { + return &FallManager{e: e} +} + +// SetFallDistance sets the fall distance of the entity. +func (f *FallManager) SetFallDistance(distance float64) { + f.mu.Lock() + defer f.mu.Unlock() + f.fallDistance = distance +} + +// FallDistance returns the entity's fall distance. +func (f *FallManager) FallDistance() float64 { + f.mu.Lock() + defer f.mu.Unlock() + return f.fallDistance +} + +// ResetFallDistance resets the player's fall distance. +func (f *FallManager) ResetFallDistance() { + f.mu.Lock() + defer f.mu.Unlock() + f.fallDistance = 0 +} + +// OnGround returns whether the entity is currently considered to be on the ground. +func (f *FallManager) OnGround() bool { + return f.e.OnGround() +} + +// UpdateFallState is called to update the entities falling state. +func (f *FallManager) UpdateFallState(distanceThisTick float64) { + fallDistance := f.fallDistance + f.mu.Lock() + if f.OnGround() { + if fallDistance > 0 { + f.fall(fallDistance) + f.mu.Unlock() + f.ResetFallDistance() + } else { + f.mu.Unlock() + } + } else if distanceThisTick < fallDistance { + f.fallDistance -= distanceThisTick + } else { + f.mu.Unlock() + f.ResetFallDistance() + } +} + +// fall is called when a falling entity hits the ground. +func (f *FallManager) fall(distance float64) { + var ( + w = f.e.World() + pos = cube.PosFromVec3(f.e.Position()) + b = w.Block(pos) + dmg = distance - 3 + ) + if len(b.Model().BBox(pos, w)) == 0 { + pos = pos.Sub(cube.Pos{0, 1}) + b = w.Block(pos) + } + if h, ok := b.(entityLander); ok { + h.EntityLand(pos, w, f.e) + } + + if p, ok := f.e.(Living); ok { + if boost, ok := p.Effect(effect.JumpBoost{}); ok { + dmg -= float64(boost.Level()) + } + if dmg < 0.5 { + return + } + p.Hurt(math.Ceil(dmg), damage.SourceFall{}) + } +} + +// CheckOnGround checks if the entity is currently considered to be on the ground. +func (f *FallManager) CheckOnGround(w *world.World) bool { + box := f.e.BBox().Translate(f.e.Position()) + + b := box.Grow(1) + + min, max := cube.PosFromVec3(b.Min()), cube.PosFromVec3(b.Max()) + for x := min[0]; x <= max[0]; x++ { + for z := min[2]; z <= max[2]; z++ { + for y := min[1]; y < max[1]; y++ { + pos := cube.Pos{x, y, z} + boxList := w.Block(pos).Model().BBox(pos, w) + for _, bb := range boxList { + if bb.GrowVec3(mgl64.Vec3{0, 0.05}).Translate(pos.Vec3()).IntersectsWith(box) { + f.mu.Lock() + f.onGround = true + f.mu.Unlock() + return true + } + } + } + } + } + f.mu.Lock() + f.onGround = false + f.mu.Unlock() + return false +} diff --git a/server/entity/living.go b/server/entity/living.go index 9895149b8..cc5a72521 100644 --- a/server/entity/living.go +++ b/server/entity/living.go @@ -45,6 +45,9 @@ type Living interface { AddEffect(e effect.Effect) // RemoveEffect removes any effect that might currently be active on the entity. RemoveEffect(e effect.Type) + // Effect returns the effect instance and true if the Player has the effect. If not found, it will return an empty + // effect instance and false. + Effect(e effect.Type) (effect.Effect, bool) // Effects returns any effect currently applied to the entity. The returned effects are guaranteed not to have // expired when returned. Effects() []effect.Effect diff --git a/server/player/player.go b/server/player/player.go index 949fca45f..3c4f911c4 100644 --- a/server/player/player.go +++ b/server/player/player.go @@ -66,8 +66,7 @@ type Player struct { invisible, immobile, onGround, usingItem atomic.Bool usingSince atomic.Int64 - fireTicks atomic.Int64 - fallDistance atomic.Float64 + fireTicks atomic.Int64 cooldownMu sync.Mutex cooldowns map[itemHash]time.Time @@ -78,6 +77,7 @@ type Player struct { health *entity.HealthManager experience *entity.ExperienceManager effects *entity.EffectManager + fall *entity.FallManager lastXPPickup atomic.Value[time.Time] immunity atomic.Value[time.Time] @@ -111,6 +111,7 @@ func New(name string, skin skin.Skin, pos mgl64.Vec3) *Player { health: entity.NewHealthManager(), experience: entity.NewExperienceManager(), effects: entity.NewEffectManager(), + fall: entity.NewFallManager(p), gameMode: *atomic.NewValue[world.GameMode](world.GameModeSurvival), h: *atomic.NewValue[Handler](NopHandler{}), name: name, @@ -254,12 +255,12 @@ func (p *Player) SendToast(title, message string) { // ResetFallDistance resets the player's fall distance. func (p *Player) ResetFallDistance() { - p.fallDistance.Store(0) + p.fall.ResetFallDistance() } // FallDistance returns the player's fall distance. func (p *Player) FallDistance() float64 { - return p.fallDistance.Load() + return p.fall.FallDistance() } // SendTitle sends a title to the player. The title may be configured to change the duration it is displayed @@ -465,46 +466,6 @@ func (p *Player) Heal(health float64, source healing.Source) { p.addHealth(health) } -// updateFallState is called to update the entities falling state. -func (p *Player) updateFallState(distanceThisTick float64) { - fallDistance := p.fallDistance.Load() - if p.OnGround() { - if fallDistance > 0 { - p.fall(fallDistance) - p.ResetFallDistance() - } - } else if distanceThisTick < fallDistance { - p.fallDistance.Sub(distanceThisTick) - } else { - p.ResetFallDistance() - } -} - -// fall is called when a falling entity hits the ground. -func (p *Player) fall(distance float64) { - var ( - w = p.World() - pos = cube.PosFromVec3(p.Position()) - b = w.Block(pos) - dmg = distance - 3 - ) - if len(b.Model().BBox(pos, w)) == 0 { - pos = pos.Sub(cube.Pos{0, 1}) - b = w.Block(pos) - } - if h, ok := b.(block.EntityLander); ok { - h.EntityLand(pos, w, p) - } - - if boost, ok := p.Effect(effect.JumpBoost{}); ok { - dmg -= float64(boost.Level()) - } - if dmg < 0.5 { - return - } - p.Hurt(math.Ceil(dmg), damage.SourceFall{}) -} - // Hurt hurts the player for a given amount of damage. The source passed represents the cause of the damage, // for example damage.SourceEntityAttack if the player is attacked by another entity. // If the final damage exceeds the health that the player currently has, the player is killed and will have to @@ -1842,9 +1803,9 @@ func (p *Player) Move(deltaPos mgl64.Vec3, deltaYaw, deltaPitch float64) { } p.checkBlockCollisions(w) - p.onGround.Store(p.checkOnGround(w)) + p.fall.CheckOnGround(w) - p.updateFallState(deltaPos[1]) + p.fall.UpdateFallState(deltaPos[1]) // The vertical axis isn't relevant for calculation of exhaustion points. deltaPos[1] = 0 @@ -2047,7 +2008,7 @@ func (p *Player) Tick(w *world.World, current int64) { } p.checkBlockCollisions(w) - p.onGround.Store(p.checkOnGround(w)) + p.fall.CheckOnGround(w) p.tickFood(w) p.effects.Tick(p) @@ -2160,29 +2121,6 @@ func (p *Player) checkBlockCollisions(w *world.World) { } } -// checkOnGround checks if the player is currently considered to be on the ground. -func (p *Player) checkOnGround(w *world.World) bool { - box := p.BBox().Translate(p.Position()) - - b := box.Grow(1) - - min, max := cube.PosFromVec3(b.Min()), cube.PosFromVec3(b.Max()) - for x := min[0]; x <= max[0]; x++ { - for z := min[2]; z <= max[2]; z++ { - for y := min[1]; y < max[1]; y++ { - pos := cube.Pos{x, y, z} - boxList := w.Block(pos).Model().BBox(pos, w) - for _, bb := range boxList { - if bb.GrowVec3(mgl64.Vec3{0, 0.05}).Translate(pos.Vec3()).IntersectsWith(box) { - return true - } - } - } - } - } - return false -} - // BBox returns the axis aligned bounding box of the player. func (p *Player) BBox() cube.BBox { s := p.Scale() @@ -2213,7 +2151,7 @@ func (p *Player) OnGround() bool { if p.session() == session.Nop { return p.mc.OnGround() } - return p.onGround.Load() + return p.fall.OnGround() } // EyeHeight returns the eye height of the player: 1.62, or 0.52 if the player is swimming. @@ -2431,7 +2369,7 @@ func (p *Player) load(data Data) { p.AddEffect(potion) } p.fireTicks.Store(data.FireTicks) - p.fallDistance.Store(data.FallDistance) + p.fall.SetFallDistance(data.FallDistance) p.loadInventory(data.Inventory) } @@ -2480,7 +2418,7 @@ func (p *Player) Data() Data { }, Effects: p.Effects(), FireTicks: p.fireTicks.Load(), - FallDistance: p.fallDistance.Load(), + FallDistance: p.fall.FallDistance(), Dimension: p.World().Dimension().EncodeDimension(), } } From 7c4ba2ab0b79919bc58a72b0d23b438a6d7b392c Mon Sep 17 00:00:00 2001 From: Hashim <13991048+Prim69@users.noreply.github.com> Date: Sun, 10 Jul 2022 02:24:16 -0400 Subject: [PATCH 04/10] e --- server/entity/fall.go | 1 + 1 file changed, 1 insertion(+) diff --git a/server/entity/fall.go b/server/entity/fall.go index 59c4af3e4..68c112a38 100644 --- a/server/entity/fall.go +++ b/server/entity/fall.go @@ -75,6 +75,7 @@ func (f *FallManager) UpdateFallState(distanceThisTick float64) { } } else if distanceThisTick < fallDistance { f.fallDistance -= distanceThisTick + f.mu.Unlock() } else { f.mu.Unlock() f.ResetFallDistance() From 4c3fc4b4944f0539db3b623d0165c753bfda43fb Mon Sep 17 00:00:00 2001 From: Hashim <13991048+Prim69@users.noreply.github.com> Date: Sun, 10 Jul 2022 02:28:32 -0400 Subject: [PATCH 05/10] Update fall.go --- server/entity/fall.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server/entity/fall.go b/server/entity/fall.go index 68c112a38..7f8d8ccab 100644 --- a/server/entity/fall.go +++ b/server/entity/fall.go @@ -58,6 +58,11 @@ func (f *FallManager) ResetFallDistance() { // OnGround returns whether the entity is currently considered to be on the ground. func (f *FallManager) OnGround() bool { + if false { // todo: if f.e is a player + f.mu.Lock() + defer f.mu.Unlock() + return f.onGround + } return f.e.OnGround() } From 0e009bd30d36592b9b88a869eef700127e35bafd Mon Sep 17 00:00:00 2001 From: Hashim <13991048+Prim69@users.noreply.github.com> Date: Sun, 10 Jul 2022 03:06:02 -0400 Subject: [PATCH 06/10] mutex --- server/entity/fall.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/server/entity/fall.go b/server/entity/fall.go index 7f8d8ccab..7c4d1e70f 100644 --- a/server/entity/fall.go +++ b/server/entity/fall.go @@ -68,21 +68,19 @@ func (f *FallManager) OnGround() bool { // UpdateFallState is called to update the entities falling state. func (f *FallManager) UpdateFallState(distanceThisTick float64) { - fallDistance := f.fallDistance f.mu.Lock() + fallDistance := f.fallDistance + f.mu.Unlock() if f.OnGround() { if fallDistance > 0 { f.fall(fallDistance) - f.mu.Unlock() f.ResetFallDistance() - } else { - f.mu.Unlock() } } else if distanceThisTick < fallDistance { + f.mu.Lock() f.fallDistance -= distanceThisTick f.mu.Unlock() } else { - f.mu.Unlock() f.ResetFallDistance() } } From 46c6310f668422ac205c5013c24c5ff9feca24c6 Mon Sep 17 00:00:00 2001 From: Hashim <13991048+Prim69@users.noreply.github.com> Date: Sun, 10 Jul 2022 15:18:01 -0400 Subject: [PATCH 07/10] dont check onGround with the fall manager --- server/entity/fall.go | 43 +---------------------------------------- server/player/player.go | 29 ++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 45 deletions(-) diff --git a/server/entity/fall.go b/server/entity/fall.go index 7c4d1e70f..b16389657 100644 --- a/server/entity/fall.go +++ b/server/entity/fall.go @@ -5,7 +5,6 @@ import ( "github.com/df-mc/dragonfly/server/entity/damage" "github.com/df-mc/dragonfly/server/entity/effect" "github.com/df-mc/dragonfly/server/world" - "github.com/go-gl/mathgl/mgl64" "math" "sync" ) @@ -15,7 +14,6 @@ type FallManager struct { mu sync.Mutex e fallEntity fallDistance float64 - onGround bool } // fallEntity is an entity that can fall. @@ -56,22 +54,12 @@ func (f *FallManager) ResetFallDistance() { f.fallDistance = 0 } -// OnGround returns whether the entity is currently considered to be on the ground. -func (f *FallManager) OnGround() bool { - if false { // todo: if f.e is a player - f.mu.Lock() - defer f.mu.Unlock() - return f.onGround - } - return f.e.OnGround() -} - // UpdateFallState is called to update the entities falling state. func (f *FallManager) UpdateFallState(distanceThisTick float64) { f.mu.Lock() fallDistance := f.fallDistance f.mu.Unlock() - if f.OnGround() { + if f.e.OnGround() { if fallDistance > 0 { f.fall(fallDistance) f.ResetFallDistance() @@ -111,32 +99,3 @@ func (f *FallManager) fall(distance float64) { p.Hurt(math.Ceil(dmg), damage.SourceFall{}) } } - -// CheckOnGround checks if the entity is currently considered to be on the ground. -func (f *FallManager) CheckOnGround(w *world.World) bool { - box := f.e.BBox().Translate(f.e.Position()) - - b := box.Grow(1) - - min, max := cube.PosFromVec3(b.Min()), cube.PosFromVec3(b.Max()) - for x := min[0]; x <= max[0]; x++ { - for z := min[2]; z <= max[2]; z++ { - for y := min[1]; y < max[1]; y++ { - pos := cube.Pos{x, y, z} - boxList := w.Block(pos).Model().BBox(pos, w) - for _, bb := range boxList { - if bb.GrowVec3(mgl64.Vec3{0, 0.05}).Translate(pos.Vec3()).IntersectsWith(box) { - f.mu.Lock() - f.onGround = true - f.mu.Unlock() - return true - } - } - } - } - } - f.mu.Lock() - f.onGround = false - f.mu.Unlock() - return false -} diff --git a/server/player/player.go b/server/player/player.go index 3c4f911c4..03c83937f 100644 --- a/server/player/player.go +++ b/server/player/player.go @@ -1803,7 +1803,7 @@ func (p *Player) Move(deltaPos mgl64.Vec3, deltaYaw, deltaPitch float64) { } p.checkBlockCollisions(w) - p.fall.CheckOnGround(w) + p.onGround.Store(p.checkOnGround(w)) p.fall.UpdateFallState(deltaPos[1]) @@ -2008,7 +2008,7 @@ func (p *Player) Tick(w *world.World, current int64) { } p.checkBlockCollisions(w) - p.fall.CheckOnGround(w) + p.onGround.Store(p.checkOnGround(w)) p.tickFood(w) p.effects.Tick(p) @@ -2121,6 +2121,29 @@ func (p *Player) checkBlockCollisions(w *world.World) { } } +// checkOnGround checks if the player is currently considered to be on the ground. +func (p *Player) checkOnGround(w *world.World) bool { + box := p.BBox().Translate(p.Position()) + + b := box.Grow(1) + + min, max := cube.PosFromVec3(b.Min()), cube.PosFromVec3(b.Max()) + for x := min[0]; x <= max[0]; x++ { + for z := min[2]; z <= max[2]; z++ { + for y := min[1]; y < max[1]; y++ { + pos := cube.Pos{x, y, z} + boxList := w.Block(pos).Model().BBox(pos, w) + for _, bb := range boxList { + if bb.GrowVec3(mgl64.Vec3{0, 0.05}).Translate(pos.Vec3()).IntersectsWith(box) { + return true + } + } + } + } + } + return false +} + // BBox returns the axis aligned bounding box of the player. func (p *Player) BBox() cube.BBox { s := p.Scale() @@ -2151,7 +2174,7 @@ func (p *Player) OnGround() bool { if p.session() == session.Nop { return p.mc.OnGround() } - return p.fall.OnGround() + return p.onGround.Load() } // EyeHeight returns the eye height of the player: 1.62, or 0.52 if the player is swimming. From a67a64eaf40b00da377a0fea99a5a55dc4dbedc1 Mon Sep 17 00:00:00 2001 From: Hashim <13991048+Prim69@users.noreply.github.com> Date: Thu, 14 Jul 2022 19:18:55 -0400 Subject: [PATCH 08/10] W atomic --- server/entity/fall.go | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/server/entity/fall.go b/server/entity/fall.go index b16389657..e05bb50df 100644 --- a/server/entity/fall.go +++ b/server/entity/fall.go @@ -1,19 +1,18 @@ package entity import ( + "github.com/df-mc/atomic" "github.com/df-mc/dragonfly/server/block/cube" "github.com/df-mc/dragonfly/server/entity/damage" "github.com/df-mc/dragonfly/server/entity/effect" "github.com/df-mc/dragonfly/server/world" "math" - "sync" ) // FallManager handles entities that can fall. type FallManager struct { - mu sync.Mutex e fallEntity - fallDistance float64 + fallDistance atomic.Float64 } // fallEntity is an entity that can fall. @@ -35,39 +34,29 @@ func NewFallManager(e fallEntity) *FallManager { // SetFallDistance sets the fall distance of the entity. func (f *FallManager) SetFallDistance(distance float64) { - f.mu.Lock() - defer f.mu.Unlock() - f.fallDistance = distance + f.fallDistance.Store(distance) } // FallDistance returns the entity's fall distance. func (f *FallManager) FallDistance() float64 { - f.mu.Lock() - defer f.mu.Unlock() - return f.fallDistance + return f.fallDistance.Load() } // ResetFallDistance resets the player's fall distance. func (f *FallManager) ResetFallDistance() { - f.mu.Lock() - defer f.mu.Unlock() - f.fallDistance = 0 + f.fallDistance.Store(0) } // UpdateFallState is called to update the entities falling state. func (f *FallManager) UpdateFallState(distanceThisTick float64) { - f.mu.Lock() - fallDistance := f.fallDistance - f.mu.Unlock() + fallDistance := f.fallDistance.Load() if f.e.OnGround() { if fallDistance > 0 { f.fall(fallDistance) f.ResetFallDistance() } } else if distanceThisTick < fallDistance { - f.mu.Lock() - f.fallDistance -= distanceThisTick - f.mu.Unlock() + f.fallDistance.Sub(distanceThisTick) } else { f.ResetFallDistance() } From c595fb8ff1a01b5e22076ee24594ddd97b16c4f3 Mon Sep 17 00:00:00 2001 From: Hashim <13991048+Prim69@users.noreply.github.com> Date: Thu, 14 Jul 2022 20:24:04 -0400 Subject: [PATCH 09/10] FallManager.fall doc --- server/entity/fall.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/entity/fall.go b/server/entity/fall.go index e05bb50df..d4894e6cc 100644 --- a/server/entity/fall.go +++ b/server/entity/fall.go @@ -62,7 +62,8 @@ func (f *FallManager) UpdateFallState(distanceThisTick float64) { } } -// fall is called when a falling entity hits the ground. +// fall is called when a falling entity hits the ground. It handles the landing, calling EntityLand if needed, +// and applying fall damage to living entities. func (f *FallManager) fall(distance float64) { var ( w = f.e.World() From a577dac14e5905bf5ccff5e39539272dfa53776c Mon Sep 17 00:00:00 2001 From: Hashim <13991048+Prim69@users.noreply.github.com> Date: Fri, 15 Jul 2022 01:34:38 -0400 Subject: [PATCH 10/10] e --- server/entity/fall.go | 4 ++-- server/entity/falling_block.go | 24 ++++++++++++------------ server/player/player.go | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/server/entity/fall.go b/server/entity/fall.go index d4894e6cc..a2ae5e80f 100644 --- a/server/entity/fall.go +++ b/server/entity/fall.go @@ -48,9 +48,9 @@ func (f *FallManager) ResetFallDistance() { } // UpdateFallState is called to update the entities falling state. -func (f *FallManager) UpdateFallState(distanceThisTick float64) { +func (f *FallManager) UpdateFallState(distanceThisTick float64, checkOnGround bool) { fallDistance := f.fallDistance.Load() - if f.e.OnGround() { + if checkOnGround && f.e.OnGround() { if fallDistance > 0 { f.fall(fallDistance) f.ResetFallDistance() diff --git a/server/entity/falling_block.go b/server/entity/falling_block.go index b491df6db..fafc68a6e 100644 --- a/server/entity/falling_block.go +++ b/server/entity/falling_block.go @@ -2,7 +2,6 @@ package entity import ( "fmt" - "github.com/df-mc/atomic" "github.com/df-mc/dragonfly/server/block/cube" "github.com/df-mc/dragonfly/server/entity/damage" "github.com/df-mc/dragonfly/server/internal/nbtconv" @@ -17,8 +16,8 @@ import ( type FallingBlock struct { transform - block world.Block - fallDistance atomic.Float64 + block world.Block + fall *FallManager c *MovementComputer } @@ -33,6 +32,7 @@ func NewFallingBlock(block world.Block, pos mgl64.Vec3) *FallingBlock { DragBeforeGravity: true, }, } + b.fall = NewFallManager(b) b.transform = newTransform(b, pos) return b } @@ -59,7 +59,7 @@ func (f *FallingBlock) Block() world.Block { // FallDistance ... func (f *FallingBlock) FallDistance() float64 { - return f.fallDistance.Load() + return f.fall.FallDistance() } // damager ... @@ -77,6 +77,11 @@ type landable interface { Landed(w *world.World, pos cube.Pos) } +// OnGround ... +func (f *FallingBlock) OnGround() bool { + return f.c.OnGround() +} + // Tick ... func (f *FallingBlock) Tick(w *world.World, _ int64) { f.mu.Lock() @@ -86,12 +91,7 @@ func (f *FallingBlock) Tick(w *world.World, _ int64) { m.Send() - distThisTick := f.vel.Y() - if distThisTick < f.fallDistance.Load() { - f.fallDistance.Sub(distThisTick) - } else { - f.fallDistance.Store(0) - } + f.fall.UpdateFallState(f.vel.Y(), false) pos := cube.PosFromVec3(m.pos) if pos[1] < w.Range()[0] { @@ -101,7 +101,7 @@ func (f *FallingBlock) Tick(w *world.World, _ int64) { if a, ok := f.block.(Solidifiable); (ok && a.Solidifies(pos, w)) || f.c.OnGround() { if d, ok := f.block.(damager); ok { damagePerBlock, maxDamage := d.Damage() - if dist := math.Ceil(f.fallDistance.Load() - 1.0); dist > 0 { + if dist := math.Ceil(f.FallDistance() - 1.0); dist > 0 { force := math.Min(math.Floor(dist*damagePerBlock), maxDamage) for _, e := range w.EntitiesWithin(f.BBox().Translate(m.pos).Grow(0.05), f.ignores) { e.(Living).Hurt(force, damage.SourceBlock{Block: f.block}) @@ -137,7 +137,7 @@ func (f *FallingBlock) DecodeNBT(data map[string]any) any { } n := NewFallingBlock(b, nbtconv.MapVec3(data, "Pos")) n.SetVelocity(nbtconv.MapVec3(data, "Motion")) - n.fallDistance.Store(nbtconv.Map[float64](data, "FallDistance")) + n.fall.SetFallDistance(nbtconv.Map[float64](data, "FallDistance")) return n } diff --git a/server/player/player.go b/server/player/player.go index dad1b6aa7..f65c9d105 100644 --- a/server/player/player.go +++ b/server/player/player.go @@ -1861,7 +1861,7 @@ func (p *Player) Move(deltaPos mgl64.Vec3, deltaYaw, deltaPitch float64) { p.checkBlockCollisions(w) p.onGround.Store(p.checkOnGround(w)) - p.fall.UpdateFallState(deltaPos[1]) + p.fall.UpdateFallState(deltaPos[1], true) // The vertical axis isn't relevant for calculation of exhaustion points. deltaPos[1] = 0