diff --git a/server/item/goat_horn.go b/server/item/goat_horn.go index ce7b693c3..01d84884c 100644 --- a/server/item/goat_horn.go +++ b/server/item/goat_horn.go @@ -29,24 +29,29 @@ func (GoatHorn) Cooldown() time.Duration { func (g GoatHorn) Use(tx *world.Tx, user User, ctx *UseContext) bool { tx.PlaySound(user.Position(), sound.GoatHorn{Horn: g.Type}) time.AfterFunc(time.Second, func() { - if !user.UsingItem() { - // We aren't using the goat horn anymore. - return - } - - held, _ := user.HeldItems() - if _, ok := held.Item().(GoatHorn); !ok { - // We aren't holding the goat horn anymore. - return - } - - // The goat horn is forcefully released by the server after a second. If the client released the item itself, - // before a second, this shouldn't do anything. - user.ReleaseItem() + user.H().ExecWorld(g.releaseItem) }) return true } +// releaseItem releases the goat horn item if a user is still using it. +func (g GoatHorn) releaseItem(_ *world.Tx, e world.Entity) { + user := e.(User) + if !user.UsingItem() { + // We aren't using the goat horn anymore. + return + } + held, _ := user.HeldItems() + if _, ok := held.Item().(GoatHorn); !ok { + // We aren't holding the goat horn anymore. + return + } + // The goat horn is forcefully released by the server after a second. If the + // client released the item itself, before a second, this shouldn't do + // anything. + user.ReleaseItem() +} + // EncodeItem ... func (g GoatHorn) EncodeItem() (name string, meta int16) { return "minecraft:goat_horn", int16(g.Type.Uint8()) diff --git a/server/player/player.go b/server/player/player.go index 343a041c3..fed34b75a 100644 --- a/server/player/player.go +++ b/server/player/player.go @@ -802,22 +802,30 @@ func (p *Player) kill(src world.DamageSource) { p.deathPos, p.deathDimension = &pos, p.tx.World().Dimension() - // Wait a little before removing the entity. The client displays a death animation while the player is dying. + // Wait a little before removing the entity. The client displays a death + // animation while the player is dying. time.AfterFunc(time.Millisecond*1100, func() { - if p.session() == session.Nop { - _ = p.Close() - return - } - if p.Dead() { - p.SetInvisible() - // We have an actual client connected to this player: We change its 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.H().ExecWorld(finishDying) }) } +// finishDying completes the death of a player, removing it from the world. +func finishDying(_ *world.Tx, e world.Entity) { + p := e.(*Player) + if p.session() == session.Nop { + _ = p.Close() + return + } + if p.Dead() { + p.SetInvisible() + // We have an actual client connected to this player: We change its + // 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() + } +} + // dropItems drops all items and experience of the Player on the ground in random directions. func (p *Player) dropItems() { pos := p.Position()