From e9ed5f25e870a53caa94c9ad9faeb38720580974 Mon Sep 17 00:00:00 2001 From: Sandertv <st.ten.veldhuis@gmail.com> Date: Sun, 5 Jan 2025 17:08:44 +0100 Subject: [PATCH] player/player.go: Handle block breaking server-side. Resolves #960. Also fixes weird breaking bugs because `p.breaking` was never set to false(!) --- server/player/player.go | 24 +++++++++++++----------- server/session/handler_player_action.go | 17 +++-------------- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/server/player/player.go b/server/player/player.go index 0d6a75cea..9080e24f3 100644 --- a/server/player/player.go +++ b/server/player/player.go @@ -89,9 +89,10 @@ type playerData struct { breaking bool breakingPos cube.Pos + breakingFace cube.Face lastBreakDuration time.Duration - breakParticleCounter uint32 + breakCounter uint32 hunger *hungerManager @@ -1730,7 +1731,7 @@ func (p *Player) StartBreaking(pos cube.Pos, face cube.Face) { punchable.Punch(pos, face, p.tx, p) } - p.breaking = true + p.breaking, p.breakingFace = true, face p.SwingArm() if p.GameMode().CreativeInventory() { @@ -1786,7 +1787,7 @@ func (p *Player) AbortBreaking() { if !p.breaking { return } - p.breaking, p.breakParticleCounter = true, 0 + p.breaking, p.breakCounter = false, 0 for _, viewer := range p.viewers() { viewer.ViewBlockAction(p.breakingPos, block.StopCrackAction{}) } @@ -1800,19 +1801,17 @@ func (p *Player) ContinueBreaking(face cube.Face) { return } pos := p.breakingPos - - p.SwingArm() - b := p.tx.Block(pos) p.tx.AddParticle(pos.Vec3(), particle.PunchBlock{Block: b, Face: face}) - if p.breakParticleCounter += 1; p.breakParticleCounter%5 == 0 { + if p.breakCounter++; p.breakCounter%5 == 0 { + p.SwingArm() + // We send this sound only every so often. Vanilla doesn't send it every tick while breaking // either. Every 5 ticks seems accurate. - p.tx.PlaySound(pos.Vec3(), sound.BlockBreaking{Block: p.tx.Block(pos)}) + p.tx.PlaySound(pos.Vec3(), sound.BlockBreaking{Block: b}) } - breakTime := p.breakTime(pos) - if breakTime != p.lastBreakDuration { + if breakTime := p.breakTime(pos); breakTime != p.lastBreakDuration { for _, viewer := range p.viewers() { viewer.ViewBlockAction(pos, block.ContinueCrackAction{BreakTime: breakTime}) } @@ -2348,7 +2347,7 @@ func (p *Player) Tick(tx *world.Tx, current int64) { p.tickFood() p.tickAirSupply() - if p.Position()[1] < float64(p.tx.Range()[0]) && p.GameMode().AllowsTakingDamage() && current%10 == 0 { + if p.Position()[1] < float64(p.tx.Range()[0]) { p.Hurt(4, entity.VoidDamageSource{}) } if p.insideOfSolid() { @@ -2380,6 +2379,9 @@ func (p *Player) Tick(tx *world.Tx, current int64) { c.ContinueCharge(p, tx, p.useContext(), p.useDuration()) } } + if p.breaking { + p.ContinueBreaking(p.breakingFace) + } for it, ti := range p.cooldowns { if time.Now().After(ti) { diff --git a/server/session/handler_player_action.go b/server/session/handler_player_action.go index 74048d338..1f6d980de 100644 --- a/server/session/handler_player_action.go +++ b/server/session/handler_player_action.go @@ -45,19 +45,8 @@ func handlePlayerAction(action int32, face int32, pos protocol.BlockPos, entityR defer s.swingingArm.Store(false) c.FinishBreaking() case protocol.PlayerActionCrackBreak: - s.swingingArm.Store(true) - defer s.swingingArm.Store(false) - - newPos := cube.Pos{int(pos[0]), int(pos[1]), int(pos[2])} - - // Sometimes no new position will be sent using a StartBreak action, so we need to detect a change in the - // block to be broken by comparing positions. - if newPos != s.breakingPos { - s.breakingPos = newPos - c.StartBreaking(newPos, cube.Face(face)) - return nil - } - c.ContinueBreaking(cube.Face(face)) + // Don't do anything for this action. It is no longer used. Block + // cracking is done fully server-side. case protocol.PlayerActionStartItemUseOn: // TODO: Properly utilize these actions. case protocol.PlayerActionStopItemUseOn: @@ -65,7 +54,7 @@ func handlePlayerAction(action int32, face int32, pos protocol.BlockPos, entityR case protocol.PlayerActionStartBuildingBlock: // Don't do anything for this action. case protocol.PlayerActionCreativePlayerDestroyBlock: - // Don't do anything for this action. + // Don't do anything for this action. case protocol.PlayerActionMissedSwing: s.swingingArm.Store(true) defer s.swingingArm.Store(false)