github.com/df-mc/dragonfly@v0.9.13/server/player/player.go (about)

     1  package player
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"math/rand"
     7  	"net"
     8  	"strings"
     9  	"sync"
    10  	"time"
    11  
    12  	"github.com/df-mc/atomic"
    13  	"github.com/df-mc/dragonfly/server/block"
    14  	"github.com/df-mc/dragonfly/server/block/cube"
    15  	"github.com/df-mc/dragonfly/server/block/model"
    16  	"github.com/df-mc/dragonfly/server/cmd"
    17  	"github.com/df-mc/dragonfly/server/entity"
    18  	"github.com/df-mc/dragonfly/server/entity/effect"
    19  	"github.com/df-mc/dragonfly/server/event"
    20  	"github.com/df-mc/dragonfly/server/internal/sliceutil"
    21  	"github.com/df-mc/dragonfly/server/item"
    22  	"github.com/df-mc/dragonfly/server/item/enchantment"
    23  	"github.com/df-mc/dragonfly/server/item/inventory"
    24  	"github.com/df-mc/dragonfly/server/player/bossbar"
    25  	"github.com/df-mc/dragonfly/server/player/chat"
    26  	"github.com/df-mc/dragonfly/server/player/form"
    27  	"github.com/df-mc/dragonfly/server/player/scoreboard"
    28  	"github.com/df-mc/dragonfly/server/player/skin"
    29  	"github.com/df-mc/dragonfly/server/player/title"
    30  	"github.com/df-mc/dragonfly/server/session"
    31  	"github.com/df-mc/dragonfly/server/world"
    32  	"github.com/df-mc/dragonfly/server/world/particle"
    33  	"github.com/df-mc/dragonfly/server/world/sound"
    34  	"github.com/go-gl/mathgl/mgl64"
    35  	"github.com/google/uuid"
    36  	"golang.org/x/text/language"
    37  )
    38  
    39  // Player is an implementation of a player entity. It has methods that implement the behaviour that players
    40  // need to play in the world.
    41  type Player struct {
    42  	name                                string
    43  	uuid                                uuid.UUID
    44  	xuid                                string
    45  	locale                              language.Tag
    46  	pos, vel                            atomic.Value[mgl64.Vec3]
    47  	nameTag                             atomic.Value[string]
    48  	scoreTag                            atomic.Value[string]
    49  	yaw, pitch, absorptionHealth, scale atomic.Float64
    50  	once                                sync.Once
    51  
    52  	gameMode atomic.Value[world.GameMode]
    53  
    54  	skin atomic.Value[skin.Skin]
    55  	// s holds the session of the player. This field should not be used directly, but instead,
    56  	// Player.session() should be called.
    57  	s atomic.Value[*session.Session]
    58  	// h holds the current Handler of the player. It may be changed at any time by calling the Handle method.
    59  	h atomic.Value[Handler]
    60  
    61  	inv, offHand, enderChest *inventory.Inventory
    62  	armour                   *inventory.Armour
    63  	heldSlot                 *atomic.Uint32
    64  
    65  	sneaking, sprinting, swimming, gliding, flying,
    66  	invisible, immobile, onGround, usingItem atomic.Bool
    67  	usingSince atomic.Int64
    68  
    69  	glideTicks   atomic.Int64
    70  	fireTicks    atomic.Int64
    71  	fallDistance atomic.Float64
    72  
    73  	breathing         bool
    74  	airSupplyTicks    atomic.Int64
    75  	maxAirSupplyTicks atomic.Int64
    76  
    77  	cooldownMu sync.Mutex
    78  	cooldowns  map[string]time.Time
    79  	// lastTickedWorld holds the world that the player was in, in the last tick.
    80  	lastTickedWorld *world.World
    81  
    82  	speed      atomic.Float64
    83  	health     *entity.HealthManager
    84  	experience *entity.ExperienceManager
    85  	effects    *entity.EffectManager
    86  
    87  	lastXPPickup  atomic.Value[time.Time]
    88  	immunityTicks atomic.Int64
    89  
    90  	deathMu        sync.Mutex
    91  	deathPos       *mgl64.Vec3
    92  	deathDimension world.Dimension
    93  
    94  	enchantSeed atomic.Int64
    95  
    96  	mc *entity.MovementComputer
    97  
    98  	collidedVertically, collidedHorizontally atomic.Bool
    99  
   100  	breaking          atomic.Bool
   101  	breakingPos       atomic.Value[cube.Pos]
   102  	lastBreakDuration time.Duration
   103  
   104  	breakParticleCounter atomic.Uint32
   105  
   106  	hunger *hungerManager
   107  }
   108  
   109  // New returns a new initialised player. A random UUID is generated for the player, so that it may be
   110  // identified over network. You can either pass on player data you want to load or
   111  // you can leave the data as nil to use default data.
   112  func New(name string, skin skin.Skin, pos mgl64.Vec3) *Player {
   113  	p := &Player{}
   114  	*p = Player{
   115  		inv: inventory.New(36, func(slot int, before, after item.Stack) {
   116  			if slot == int(p.heldSlot.Load()) {
   117  				p.broadcastItems(slot, before, after)
   118  			}
   119  		}),
   120  		enderChest:        inventory.New(27, nil),
   121  		uuid:              uuid.New(),
   122  		offHand:           inventory.New(1, p.broadcastItems),
   123  		armour:            inventory.NewArmour(p.broadcastArmour),
   124  		hunger:            newHungerManager(),
   125  		health:            entity.NewHealthManager(20, 20),
   126  		experience:        entity.NewExperienceManager(),
   127  		effects:           entity.NewEffectManager(),
   128  		gameMode:          *atomic.NewValue[world.GameMode](world.GameModeSurvival),
   129  		h:                 *atomic.NewValue[Handler](NopHandler{}),
   130  		name:              name,
   131  		skin:              *atomic.NewValue(skin),
   132  		speed:             *atomic.NewFloat64(0.1),
   133  		nameTag:           *atomic.NewValue(name),
   134  		heldSlot:          atomic.NewUint32(0),
   135  		locale:            language.BritishEnglish,
   136  		breathing:         true,
   137  		airSupplyTicks:    *atomic.NewInt64(300),
   138  		maxAirSupplyTicks: *atomic.NewInt64(300),
   139  		enchantSeed:       *atomic.NewInt64(rand.Int63()),
   140  		scale:             *atomic.NewFloat64(1),
   141  		pos:               *atomic.NewValue(pos),
   142  		cooldowns:         make(map[string]time.Time),
   143  		mc:                &entity.MovementComputer{Gravity: 0.08, Drag: 0.02, DragBeforeGravity: true},
   144  	}
   145  	return p
   146  }
   147  
   148  // NewWithSession returns a new player for a network session, so that the network session can control the
   149  // player.
   150  // A set of additional fields must be provided to initialise the player with the client's data, such as the
   151  // name and the skin of the player. You can either pass on player data you want to load or
   152  // you can leave the data as nil to use default data.
   153  func NewWithSession(name, xuid string, uuid uuid.UUID, skin skin.Skin, s *session.Session, pos mgl64.Vec3, data *Data) *Player {
   154  	p := New(name, skin, pos)
   155  	p.s, p.uuid, p.xuid, p.skin = *atomic.NewValue(s), uuid, xuid, *atomic.NewValue(skin)
   156  	p.inv, p.offHand, p.enderChest, p.armour, p.heldSlot = s.HandleInventories()
   157  	p.locale, _ = language.Parse(strings.Replace(s.ClientData().LanguageCode, "_", "-", 1))
   158  	if data != nil {
   159  		p.load(*data)
   160  	}
   161  	return p
   162  }
   163  
   164  // Type returns the world.EntityType for the Player.
   165  func (p *Player) Type() world.EntityType {
   166  	return Type{}
   167  }
   168  
   169  // Name returns the username of the player. If the player is controlled by a client, it is the username of
   170  // the client. (Typically the XBOX Live name)
   171  func (p *Player) Name() string {
   172  	return p.name
   173  }
   174  
   175  // UUID returns the UUID of the player. This UUID will remain consistent with an XBOX Live account, and will,
   176  // unlike the name of the player, never change.
   177  // It is therefore recommended using the UUID over the name of the player. Additionally, it is recommended to
   178  // use the UUID over the XUID because of its standard format.
   179  func (p *Player) UUID() uuid.UUID {
   180  	return p.uuid
   181  }
   182  
   183  // XUID returns the XBOX Live user ID of the player. It will remain consistent with the XBOX Live account,
   184  // and will not change in the lifetime of an account.
   185  // The XUID is a number that can be parsed as an int64. No more information on what it represents is
   186  // available, and the UUID should be preferred.
   187  // The XUID returned is empty if the Player is not connected to a network session or if the Player is not
   188  // authenticated with XBOX Live.
   189  func (p *Player) XUID() string {
   190  	return p.xuid
   191  }
   192  
   193  // DeviceID returns the device ID of the player. If the Player is not connected to a network session, an empty string is
   194  // returned. Otherwise, the device ID the network session sent in the ClientData is returned.
   195  func (p *Player) DeviceID() string {
   196  	if p.session() == session.Nop {
   197  		return ""
   198  	}
   199  	return p.session().ClientData().DeviceID
   200  }
   201  
   202  // DeviceModel returns the device model of the player. If the Player is not connected to a network session, an empty
   203  // string is returned. Otherwise, the device model the network session sent in the ClientData is returned.
   204  func (p *Player) DeviceModel() string {
   205  	if p.session() == session.Nop {
   206  		return ""
   207  	}
   208  	return p.session().ClientData().DeviceModel
   209  }
   210  
   211  // SelfSignedID returns the self-signed ID of the player. If the Player is not connected to a network session, an empty
   212  // string is returned. Otherwise, the self-signed ID the network session sent in the ClientData is returned.
   213  func (p *Player) SelfSignedID() string {
   214  	if p.session() == session.Nop {
   215  		return ""
   216  	}
   217  	return p.session().ClientData().SelfSignedID
   218  }
   219  
   220  // Addr returns the net.Addr of the Player. If the Player is not connected to a network session, nil is returned.
   221  func (p *Player) Addr() net.Addr {
   222  	if p.session() == session.Nop {
   223  		return nil
   224  	}
   225  	return p.session().Addr()
   226  }
   227  
   228  // Skin returns the skin that a player is currently using. This skin will be visible to other players
   229  // that the player is shown to.
   230  // If the player was not connected to a network session, a default skin will be set.
   231  func (p *Player) Skin() skin.Skin {
   232  	return p.skin.Load()
   233  }
   234  
   235  // SetSkin changes the skin of the player. This skin will be visible to other players that the player
   236  // is shown to.
   237  func (p *Player) SetSkin(skin skin.Skin) {
   238  	if p.Dead() {
   239  		return
   240  	}
   241  	ctx := event.C()
   242  	if p.Handler().HandleSkinChange(ctx, &skin); ctx.Cancelled() {
   243  		p.session().ViewSkin(p)
   244  		return
   245  	}
   246  	p.skin.Store(skin)
   247  	for _, v := range p.viewers() {
   248  		v.ViewSkin(p)
   249  	}
   250  }
   251  
   252  // Locale returns the language and locale of the Player, as selected in the Player's settings.
   253  func (p *Player) Locale() language.Tag {
   254  	return p.locale
   255  }
   256  
   257  // Handle changes the current Handler of the player. As a result, events called by the player will call
   258  // handlers of the Handler passed.
   259  // Handle sets the player's Handler to NopHandler if nil is passed.
   260  func (p *Player) Handle(h Handler) {
   261  	if h == nil {
   262  		h = NopHandler{}
   263  	}
   264  	p.h.Store(h)
   265  }
   266  
   267  // Message sends a formatted message to the player. The message is formatted following the rules of
   268  // fmt.Sprintln, however the newline at the end is not written.
   269  func (p *Player) Message(a ...any) {
   270  	p.session().SendMessage(format(a))
   271  }
   272  
   273  // Messagef sends a formatted message using a specific format to the player. The message is formatted
   274  // according to the fmt.Sprintf formatting rules.
   275  func (p *Player) Messagef(f string, a ...any) {
   276  	p.session().SendMessage(fmt.Sprintf(f, a...))
   277  }
   278  
   279  // SendPopup sends a formatted popup to the player. The popup is shown above the hotbar of the player and
   280  // overwrites/is overwritten by the name of the item equipped.
   281  // The popup is formatted following the rules of fmt.Sprintln without a newline at the end.
   282  func (p *Player) SendPopup(a ...any) {
   283  	p.session().SendPopup(format(a))
   284  }
   285  
   286  // SendTip sends a tip to the player. The tip is shown in the middle of the screen of the player.
   287  // The tip is formatted following the rules of fmt.Sprintln without a newline at the end.
   288  func (p *Player) SendTip(a ...any) {
   289  	p.session().SendTip(format(a))
   290  }
   291  
   292  // SendJukeboxPopup sends a formatted jukebox popup to the player. This popup is shown above the hotbar of the player.
   293  // The popup is close to the position of an action bar message and the text has no background.
   294  func (p *Player) SendJukeboxPopup(a ...any) {
   295  	p.session().SendJukeboxPopup(format(a))
   296  }
   297  
   298  // SendToast sends a toast to the player. This toast is shown at the top of the screen, similar to achievements or pack
   299  // loading.
   300  func (p *Player) SendToast(title, message string) {
   301  	p.session().SendToast(title, message)
   302  }
   303  
   304  // ResetFallDistance resets the player's fall distance.
   305  func (p *Player) ResetFallDistance() {
   306  	p.fallDistance.Store(0)
   307  }
   308  
   309  // FallDistance returns the player's fall distance.
   310  func (p *Player) FallDistance() float64 {
   311  	return p.fallDistance.Load()
   312  }
   313  
   314  // SendTitle sends a title to the player. The title may be configured to change the duration it is displayed
   315  // and the text it shows.
   316  // If non-empty, the subtitle is shown in a smaller font below the title. The same counts for the action text
   317  // of the title, which is shown in a font similar to that of a tip/popup.
   318  func (p *Player) SendTitle(t title.Title) {
   319  	p.session().SetTitleDurations(t.FadeInDuration(), t.Duration(), t.FadeOutDuration())
   320  	if t.Text() != "" || t.Subtitle() != "" {
   321  		p.session().SendTitle(t.Text())
   322  		if t.Subtitle() != "" {
   323  			p.session().SendSubtitle(t.Subtitle())
   324  		}
   325  	}
   326  	if t.ActionText() != "" {
   327  		p.session().SendActionBarMessage(t.ActionText())
   328  	}
   329  }
   330  
   331  // SendScoreboard sends a scoreboard to the player. The scoreboard will be present indefinitely until removed
   332  // by the caller.
   333  // SendScoreboard may be called at any time to change the scoreboard of the player.
   334  func (p *Player) SendScoreboard(scoreboard *scoreboard.Scoreboard) {
   335  	p.session().SendScoreboard(scoreboard)
   336  }
   337  
   338  // RemoveScoreboard removes any scoreboard currently present on the screen of the player. Nothing happens if
   339  // the player has no scoreboard currently active.
   340  func (p *Player) RemoveScoreboard() {
   341  	p.session().RemoveScoreboard()
   342  }
   343  
   344  // SendBossBar sends a boss bar to the player, so that it will be shown indefinitely at the top of the
   345  // player's screen.
   346  // The boss bar may be removed by calling Player.RemoveBossBar().
   347  func (p *Player) SendBossBar(bar bossbar.BossBar) {
   348  	p.session().SendBossBar(bar.Text(), bar.Colour().Uint8(), bar.HealthPercentage())
   349  }
   350  
   351  // RemoveBossBar removes any boss bar currently active on the player's screen. If no boss bar is currently
   352  // present, nothing happens.
   353  func (p *Player) RemoveBossBar() {
   354  	p.session().RemoveBossBar()
   355  }
   356  
   357  // Chat writes a message in the global chat (chat.Global). The message is prefixed with the name of the
   358  // player and is formatted following the rules of fmt.Sprintln.
   359  func (p *Player) Chat(msg ...any) {
   360  	message := format(msg)
   361  	ctx := event.C()
   362  	if p.Handler().HandleChat(ctx, &message); ctx.Cancelled() {
   363  		return
   364  	}
   365  	_, _ = fmt.Fprintf(chat.Global, "<%v> %v\n", p.name, message)
   366  }
   367  
   368  // ExecuteCommand executes a command passed as the player. If the command could not be found, or if the usage
   369  // was incorrect, an error message is sent to the player. This message should start with a "/" for the command to be
   370  // recognised.
   371  func (p *Player) ExecuteCommand(commandLine string) {
   372  	if p.Dead() {
   373  		return
   374  	}
   375  	args := strings.Split(commandLine, " ")
   376  	command, ok := cmd.ByAlias(args[0][1:])
   377  	if !ok {
   378  		o := &cmd.Output{}
   379  		o.Errorf("Unknown command: %v. Please check that the command exists and that you have permission to use it.", args[0])
   380  		p.SendCommandOutput(o)
   381  		return
   382  	}
   383  	ctx := event.C()
   384  	if p.Handler().HandleCommandExecution(ctx, command, args[1:]); ctx.Cancelled() {
   385  		return
   386  	}
   387  	command.Execute(strings.Join(args[1:], " "), p)
   388  }
   389  
   390  // Transfer transfers the player to a server at the address passed. If the address could not be resolved, an
   391  // error is returned. If it is returned, the player is closed and transferred to the server.
   392  func (p *Player) Transfer(address string) error {
   393  	addr, err := net.ResolveUDPAddr("udp", address)
   394  	if err != nil {
   395  		return err
   396  	}
   397  
   398  	ctx := event.C()
   399  	if p.Handler().HandleTransfer(ctx, addr); ctx.Cancelled() {
   400  		return nil
   401  	}
   402  	p.session().Transfer(addr.IP, addr.Port)
   403  	return nil
   404  }
   405  
   406  // SendCommandOutput sends the output of a command to the player.
   407  func (p *Player) SendCommandOutput(output *cmd.Output) {
   408  	p.session().SendCommandOutput(output)
   409  }
   410  
   411  // SendForm sends a form to the player for the client to fill out. Once the client fills it out, the Submit
   412  // method of the form will be called.
   413  // Note that the client may also close the form instead of filling it out, which will result in the form not
   414  // having its Submit method called at all. Forms should never depend on the player actually filling out the
   415  // form.
   416  func (p *Player) SendForm(f form.Form) {
   417  	p.session().SendForm(f)
   418  }
   419  
   420  // ShowCoordinates enables the vanilla coordinates for the player.
   421  func (p *Player) ShowCoordinates() {
   422  	p.session().EnableCoordinates(true)
   423  }
   424  
   425  // HideCoordinates disables the vanilla coordinates for the player.
   426  func (p *Player) HideCoordinates() {
   427  	p.session().EnableCoordinates(false)
   428  }
   429  
   430  // EnableInstantRespawn enables the vanilla instant respawn for the player.
   431  func (p *Player) EnableInstantRespawn() {
   432  	p.session().EnableInstantRespawn(true)
   433  }
   434  
   435  // DisableInstantRespawn disables the vanilla instant respawn for the player.
   436  func (p *Player) DisableInstantRespawn() {
   437  	p.session().EnableInstantRespawn(false)
   438  }
   439  
   440  // SetNameTag changes the name tag displayed over the player in-game. Changing the name tag does not change
   441  // the player's name in, for example, the player list or the chat.
   442  func (p *Player) SetNameTag(name string) {
   443  	p.nameTag.Store(name)
   444  	p.updateState()
   445  }
   446  
   447  // NameTag returns the current name tag of the Player as shown in-game. It can be changed using SetNameTag.
   448  func (p *Player) NameTag() string {
   449  	return p.nameTag.Load()
   450  }
   451  
   452  // SetScoreTag changes the score tag displayed over the player in-game. The score tag is displayed under the player's
   453  // name tag.
   454  func (p *Player) SetScoreTag(a ...any) {
   455  	p.scoreTag.Store(format(a))
   456  	p.updateState()
   457  }
   458  
   459  // ScoreTag returns the current score tag of the player. It can be changed using SetScoreTag and by default is empty.
   460  func (p *Player) ScoreTag() string {
   461  	return p.scoreTag.Load()
   462  }
   463  
   464  // SetSpeed sets the speed of the player. The value passed is the blocks/tick speed that the player will then
   465  // obtain.
   466  func (p *Player) SetSpeed(speed float64) {
   467  	p.speed.Store(speed)
   468  	p.session().SendSpeed(speed)
   469  }
   470  
   471  // Speed returns the speed of the player, returning a value that indicates the blocks/tick speed. The default
   472  // speed of a player is 0.1.
   473  func (p *Player) Speed() float64 {
   474  	return p.speed.Load()
   475  }
   476  
   477  // Health returns the current health of the player. It will always be lower than Player.MaxHealth().
   478  func (p *Player) Health() float64 {
   479  	return p.health.Health()
   480  }
   481  
   482  // MaxHealth returns the maximum amount of health that a player may have. The MaxHealth will always be higher
   483  // than Player.Health().
   484  func (p *Player) MaxHealth() float64 {
   485  	return p.health.MaxHealth()
   486  }
   487  
   488  // SetMaxHealth sets the maximum health of the player. If the current health of the player is higher than the
   489  // new maximum health, the health is set to the new maximum.
   490  // SetMaxHealth panics if the max health passed is 0 or lower.
   491  func (p *Player) SetMaxHealth(health float64) {
   492  	p.health.SetMaxHealth(health)
   493  	p.session().SendHealth(p.health)
   494  }
   495  
   496  // addHealth adds health to the player's current health.
   497  func (p *Player) addHealth(health float64) {
   498  	p.health.AddHealth(health)
   499  	p.session().SendHealth(p.health)
   500  }
   501  
   502  // Heal heals the entity for a given amount of health. The source passed
   503  // represents the cause of the healing, for example entity.FoodHealingSource if
   504  // the entity healed by having a full food bar. If the health added to the
   505  // original health exceeds the entity's max health, Heal will not add the full
   506  // amount. If the health passed is negative, Heal will not do anything.
   507  func (p *Player) Heal(health float64, source world.HealingSource) {
   508  	if p.Dead() || health < 0 || !p.GameMode().AllowsTakingDamage() {
   509  		return
   510  	}
   511  	ctx := event.C()
   512  	if p.Handler().HandleHeal(ctx, &health, source); ctx.Cancelled() {
   513  		return
   514  	}
   515  	p.addHealth(health)
   516  }
   517  
   518  // updateFallState is called to update the entities falling state.
   519  func (p *Player) updateFallState(distanceThisTick float64) {
   520  	fallDistance := p.fallDistance.Load()
   521  	if p.OnGround() {
   522  		if fallDistance > 0 {
   523  			p.fall(fallDistance)
   524  			p.ResetFallDistance()
   525  		}
   526  	} else if distanceThisTick < fallDistance {
   527  		p.fallDistance.Sub(distanceThisTick)
   528  	} else {
   529  		p.ResetFallDistance()
   530  	}
   531  }
   532  
   533  // fall is called when a falling entity hits the ground.
   534  func (p *Player) fall(distance float64) {
   535  	var (
   536  		w   = p.World()
   537  		pos = cube.PosFromVec3(p.Position())
   538  		b   = w.Block(pos)
   539  	)
   540  	if len(b.Model().BBox(pos, w)) == 0 {
   541  		pos = pos.Sub(cube.Pos{0, 1})
   542  		b = w.Block(pos)
   543  	}
   544  	if h, ok := b.(block.EntityLander); ok {
   545  		h.EntityLand(pos, w, p, &distance)
   546  	}
   547  	dmg := distance - 3
   548  	if boost, ok := p.Effect(effect.JumpBoost{}); ok {
   549  		dmg -= float64(boost.Level())
   550  	}
   551  	if dmg < 0.5 {
   552  		return
   553  	}
   554  	p.Hurt(math.Ceil(dmg), entity.FallDamageSource{})
   555  }
   556  
   557  // Hurt hurts the player for a given amount of damage. The source passed
   558  // represents the cause of the damage, for example entity.AttackDamageSource if
   559  // the player is attacked by another entity. If the final damage exceeds the
   560  // health that the player currently has, the player is killed and will have to
   561  // respawn.
   562  // If the damage passed is negative, Hurt will not do anything. Hurt returns the
   563  // final damage dealt to the Player and if the Player was vulnerable to this
   564  // kind of damage.
   565  func (p *Player) Hurt(dmg float64, src world.DamageSource) (float64, bool) {
   566  	if _, ok := p.Effect(effect.FireResistance{}); (ok && src.Fire()) || p.Dead() || !p.GameMode().AllowsTakingDamage() {
   567  		return 0, false
   568  	}
   569  	immunity := time.Second / 2
   570  	ctx := event.C()
   571  	if p.Handler().HandleHurt(ctx, &dmg, &immunity, src); ctx.Cancelled() {
   572  		return 0, false
   573  	}
   574  	if dmg < 0 {
   575  		return 0, true
   576  	}
   577  
   578  	totalDamage := p.FinalDamageFrom(dmg, src)
   579  	damageLeft := totalDamage
   580  
   581  	if a := p.Absorption(); a > 0 {
   582  		if damageLeft > a {
   583  			p.SetAbsorption(0)
   584  			damageLeft -= a
   585  		} else {
   586  			p.SetAbsorption(a - damageLeft)
   587  			damageLeft = 0
   588  		}
   589  	}
   590  	p.addHealth(-damageLeft)
   591  
   592  	if src.ReducedByArmour() {
   593  		p.Exhaust(0.1)
   594  		p.Armour().Damage(dmg, p.damageItem)
   595  		var origin world.Entity
   596  		if s, ok := src.(entity.AttackDamageSource); ok {
   597  			origin = s.Attacker
   598  		} else if s, ok := src.(entity.ProjectileDamageSource); ok {
   599  			origin = s.Owner
   600  		}
   601  		if l, ok := origin.(entity.Living); ok {
   602  			thornsDmg := p.Armour().ThornsDamage(p.damageItem)
   603  			if thornsDmg > 0 {
   604  				l.Hurt(thornsDmg, enchantment.ThornsDamageSource{Owner: p})
   605  			}
   606  		}
   607  	}
   608  
   609  	w, pos := p.World(), p.Position()
   610  	for _, viewer := range p.viewers() {
   611  		viewer.ViewEntityAction(p, entity.HurtAction{})
   612  	}
   613  	if src.Fire() {
   614  		w.PlaySound(pos, sound.Burning{})
   615  	} else if _, ok := src.(entity.DrowningDamageSource); ok {
   616  		w.PlaySound(pos, sound.Drowning{})
   617  	}
   618  
   619  	p.SetAttackImmunity(immunity)
   620  	if p.Dead() {
   621  		p.kill(src)
   622  	}
   623  	return totalDamage, true
   624  }
   625  
   626  // FinalDamageFrom resolves the final damage received by the player if it is attacked by the source passed
   627  // with the damage passed. FinalDamageFrom takes into account things such as the armour worn and the
   628  // enchantments on the individual pieces.
   629  // The damage returned will be at the least 0.
   630  func (p *Player) FinalDamageFrom(dmg float64, src world.DamageSource) float64 {
   631  	dmg = math.Max(dmg, 0)
   632  
   633  	dmg -= p.Armour().DamageReduction(dmg, src)
   634  	if res, ok := p.Effect(effect.Resistance{}); ok {
   635  		dmg *= effect.Resistance{}.Multiplier(src, res.Level())
   636  	}
   637  	return dmg
   638  }
   639  
   640  // Explode ...
   641  func (p *Player) Explode(explosionPos mgl64.Vec3, impact float64, c block.ExplosionConfig) {
   642  	diff := p.Position().Sub(explosionPos)
   643  	p.Hurt(math.Floor((impact*impact+impact)*3.5*c.Size+1), entity.ExplosionDamageSource{})
   644  	p.knockBack(explosionPos, impact, diff[1]/diff.Len()*impact)
   645  }
   646  
   647  // SetAbsorption sets the absorption health of a player. This extra health shows as golden hearts and do not
   648  // actually increase the maximum health. Once the hearts are lost, they will not regenerate.
   649  // Nothing happens if a negative number is passed.
   650  func (p *Player) SetAbsorption(health float64) {
   651  	health = math.Max(health, 0)
   652  	p.absorptionHealth.Store(health)
   653  	p.session().SendAbsorption(health)
   654  }
   655  
   656  // Absorption returns the absorption health that the player has.
   657  func (p *Player) Absorption() float64 {
   658  	return p.absorptionHealth.Load()
   659  }
   660  
   661  // KnockBack knocks the player back with a given force and height. A source is passed which indicates the
   662  // source of the velocity, typically the position of an attacking entity. The source is used to calculate the
   663  // direction which the entity should be knocked back in.
   664  func (p *Player) KnockBack(src mgl64.Vec3, force, height float64) {
   665  	if p.Dead() || !p.GameMode().AllowsTakingDamage() {
   666  		return
   667  	}
   668  	p.knockBack(src, force, height)
   669  }
   670  
   671  // knockBack is an unexported function that is used to knock the player back. This function does not check if the player
   672  // can take damage or not.
   673  func (p *Player) knockBack(src mgl64.Vec3, force, height float64) {
   674  	velocity := p.Position().Sub(src)
   675  	velocity[1] = 0
   676  
   677  	if velocity.Len() != 0 {
   678  		velocity = velocity.Normalize().Mul(force)
   679  	}
   680  	velocity[1] = height
   681  
   682  	p.SetVelocity(velocity.Mul(1 - p.Armour().KnockBackResistance()))
   683  }
   684  
   685  // AttackImmune checks if the player is currently immune to entity attacks, meaning it was recently attacked.
   686  func (p *Player) AttackImmune() bool {
   687  	return p.immunityTicks.Load() > 0
   688  }
   689  
   690  // AttackImmunity returns the duration the player is immune to entity attacks.
   691  func (p *Player) AttackImmunity() time.Duration {
   692  	return time.Duration(p.immunityTicks.Load()) * time.Second / 20
   693  }
   694  
   695  // SetAttackImmunity sets the duration the player is immune to entity attacks.
   696  func (p *Player) SetAttackImmunity(d time.Duration) {
   697  	p.immunityTicks.Store(d.Milliseconds() / 50)
   698  }
   699  
   700  // Food returns the current food level of a player. The level returned is guaranteed to always be between 0
   701  // and 20. Every half drumstick is one level.
   702  func (p *Player) Food() int {
   703  	return p.hunger.Food()
   704  }
   705  
   706  // SetFood sets the food level of a player. The level passed must be in a range of 0-20. If the level passed
   707  // is negative, the food level will be set to 0. If the level exceeds 20, the food level will be set to 20.
   708  func (p *Player) SetFood(level int) {
   709  	p.hunger.SetFood(level)
   710  	p.sendFood()
   711  }
   712  
   713  // AddFood adds a number of points to the food level of the player. If the new food level is negative or if
   714  // it exceeds 20, it will be set to 0 or 20 respectively.
   715  func (p *Player) AddFood(points int) {
   716  	p.hunger.AddFood(points)
   717  	p.sendFood()
   718  }
   719  
   720  // Saturate saturates the player's food bar with the amount of food points and saturation points passed. The
   721  // total saturation of the player will never exceed its total food level.
   722  func (p *Player) Saturate(food int, saturation float64) {
   723  	p.hunger.saturate(food, saturation)
   724  	p.sendFood()
   725  }
   726  
   727  // sendFood sends the current food properties to the client.
   728  func (p *Player) sendFood() {
   729  	p.hunger.mu.RLock()
   730  	defer p.hunger.mu.RUnlock()
   731  	p.session().SendFood(p.hunger.foodLevel, p.hunger.saturationLevel, p.hunger.exhaustionLevel)
   732  }
   733  
   734  // AddEffect adds an entity.Effect to the Player. If the effect is instant, it is applied to the Player
   735  // immediately. If not, the effect is applied to the player every time the Tick method is called.
   736  // AddEffect will overwrite any effects present if the level of the effect is higher than the existing one, or
   737  // if the effects' levels are equal and the new effect has a longer duration.
   738  func (p *Player) AddEffect(e effect.Effect) {
   739  	p.session().SendEffect(p.effects.Add(e, p))
   740  	p.updateState()
   741  }
   742  
   743  // RemoveEffect removes any effect that might currently be active on the Player.
   744  func (p *Player) RemoveEffect(e effect.Type) {
   745  	p.effects.Remove(e, p)
   746  	p.session().SendEffectRemoval(e)
   747  	p.updateState()
   748  }
   749  
   750  // Effect returns the effect instance and true if the Player has the effect. If not found, it will return an empty
   751  // effect instance and false.
   752  func (p *Player) Effect(e effect.Type) (effect.Effect, bool) {
   753  	return p.effects.Effect(e)
   754  }
   755  
   756  // Effects returns any effect currently applied to the entity. The returned effects are guaranteed not to have
   757  // expired when returned.
   758  func (p *Player) Effects() []effect.Effect {
   759  	return p.effects.Effects()
   760  }
   761  
   762  // BeaconAffected ...
   763  func (*Player) BeaconAffected() bool {
   764  	return true
   765  }
   766  
   767  // Exhaust exhausts the player by the amount of points passed if the player is in survival mode. If the total
   768  // exhaustion level exceeds 4, a saturation point, or food point, if saturation is 0, will be subtracted.
   769  func (p *Player) Exhaust(points float64) {
   770  	if !p.GameMode().AllowsTakingDamage() || p.World().Difficulty().FoodRegenerates() {
   771  		return
   772  	}
   773  	before := p.hunger.Food()
   774  	p.hunger.exhaust(points)
   775  	if after := p.hunger.Food(); before != after {
   776  		// Temporarily set the food level back so that it hasn't yet changed once the event is handled.
   777  		p.hunger.SetFood(before)
   778  
   779  		ctx := event.C()
   780  		if p.Handler().HandleFoodLoss(ctx, before, &after); ctx.Cancelled() {
   781  			return
   782  		}
   783  		p.hunger.SetFood(after)
   784  		if before >= 7 && after <= 6 {
   785  			// The client will stop sprinting by itself too, but we force it just to be sure.
   786  			p.StopSprinting()
   787  		}
   788  	}
   789  	p.sendFood()
   790  }
   791  
   792  // Dead checks if the player is considered dead. True is returned if the health of the player is equal to or
   793  // lower than 0.
   794  func (p *Player) Dead() bool {
   795  	return p.Health() <= mgl64.Epsilon
   796  }
   797  
   798  // DeathPosition returns the last position the player was at when they died. If the player has never died, the third
   799  // return value will be false.
   800  func (p *Player) DeathPosition() (mgl64.Vec3, world.Dimension, bool) {
   801  	p.deathMu.Lock()
   802  	defer p.deathMu.Unlock()
   803  	if p.deathPos == nil {
   804  		return mgl64.Vec3{}, nil, false
   805  	}
   806  	return *p.deathPos, p.deathDimension, true
   807  }
   808  
   809  // kill kills the player, clearing its inventories and resetting it to its base state.
   810  func (p *Player) kill(src world.DamageSource) {
   811  	for _, viewer := range p.viewers() {
   812  		viewer.ViewEntityAction(p, entity.DeathAction{})
   813  	}
   814  
   815  	p.addHealth(-p.MaxHealth())
   816  
   817  	keepInv := false
   818  	p.Handler().HandleDeath(src, &keepInv)
   819  	p.StopSneaking()
   820  	p.StopSprinting()
   821  
   822  	w, pos := p.World(), p.Position()
   823  	if !keepInv {
   824  		p.dropContents()
   825  	}
   826  	for _, e := range p.Effects() {
   827  		p.RemoveEffect(e.Type())
   828  	}
   829  
   830  	p.deathMu.Lock()
   831  	defer p.deathMu.Unlock()
   832  	p.deathPos, p.deathDimension = &pos, w.Dimension()
   833  
   834  	// Wait a little before removing the entity. The client displays a death animation while the player is dying.
   835  	time.AfterFunc(time.Millisecond*1100, func() {
   836  		if p.session() == session.Nop {
   837  			_ = p.Close()
   838  			return
   839  		}
   840  		if p.Dead() {
   841  			p.SetInvisible()
   842  			// We have an actual client connected to this player: We change its position server side so that in
   843  			// the future, the client won't respawn on the death location when disconnecting. The client should
   844  			// not see the movement itself yet, though.
   845  			p.pos.Store(w.Spawn().Vec3())
   846  		}
   847  	})
   848  }
   849  
   850  // dropContents drops all items and experience of the Player on the ground in random directions.
   851  func (p *Player) dropContents() {
   852  	w, pos := p.World(), p.Position()
   853  	for _, orb := range entity.NewExperienceOrbs(pos, int(math.Min(float64(p.experience.Level()*7), 100))) {
   854  		orb.SetVelocity(mgl64.Vec3{(rand.Float64()*0.2 - 0.1) * 2, rand.Float64() * 0.4, (rand.Float64()*0.2 - 0.1) * 2})
   855  		w.AddEntity(orb)
   856  	}
   857  	p.experience.Reset()
   858  	p.session().SendExperience(p.experience)
   859  
   860  	p.session().EmptyUIInventory()
   861  	for _, it := range append(p.inv.Clear(), append(p.armour.Clear(), p.offHand.Clear()...)...) {
   862  		if _, ok := it.Enchantment(enchantment.CurseOfVanishing{}); ok {
   863  			continue
   864  		}
   865  		ent := entity.NewItem(it, pos)
   866  		ent.SetVelocity(mgl64.Vec3{rand.Float64()*0.2 - 0.1, 0.2, rand.Float64()*0.2 - 0.1})
   867  		w.AddEntity(ent)
   868  	}
   869  }
   870  
   871  // Respawn spawns the player after it dies, so that its health is replenished and it is spawned in the world
   872  // again. Nothing will happen if the player does not have a session connected to it.
   873  func (p *Player) Respawn() {
   874  	w := p.World()
   875  	if !p.Dead() || w == nil || p.session() == session.Nop {
   876  		return
   877  	}
   878  	p.addHealth(p.MaxHealth())
   879  	p.hunger.Reset()
   880  	p.sendFood()
   881  	p.Extinguish()
   882  	p.ResetFallDistance()
   883  
   884  	// We can use the principle here that returning through a portal of a specific dimension inside that dimension will
   885  	// always bring us back to the overworld.
   886  	w = w.PortalDestination(w.Dimension())
   887  	pos := w.PlayerSpawn(p.UUID()).Vec3Middle()
   888  
   889  	p.Handler().HandleRespawn(&pos, &w)
   890  
   891  	w.AddEntity(p)
   892  	p.Teleport(pos)
   893  	p.session().SendRespawn(pos)
   894  
   895  	p.SetVisible()
   896  }
   897  
   898  // StartSprinting makes a player start sprinting, increasing the speed of the player by 30% and making
   899  // particles show up under the feet. The player will only start sprinting if its food level is high enough.
   900  // If the player is sneaking when calling StartSprinting, it is stopped from sneaking.
   901  func (p *Player) StartSprinting() {
   902  	if !p.hunger.canSprint() && p.GameMode().AllowsTakingDamage() {
   903  		return
   904  	}
   905  	ctx := event.C()
   906  	if p.Handler().HandleToggleSprint(ctx, true); ctx.Cancelled() {
   907  		return
   908  	}
   909  	if !p.sprinting.CAS(false, true) {
   910  		return
   911  	}
   912  	p.StopSneaking()
   913  	p.SetSpeed(p.Speed() * 1.3)
   914  
   915  	p.updateState()
   916  }
   917  
   918  // Sprinting checks if the player is currently sprinting.
   919  func (p *Player) Sprinting() bool {
   920  	return p.sprinting.Load()
   921  }
   922  
   923  // StopSprinting makes a player stop sprinting, setting back the speed of the player to its original value.
   924  func (p *Player) StopSprinting() {
   925  	ctx := event.C()
   926  	if p.Handler().HandleToggleSprint(ctx, false); ctx.Cancelled() {
   927  		return
   928  	}
   929  	if !p.sprinting.CAS(true, false) {
   930  		return
   931  	}
   932  	p.SetSpeed(p.Speed() / 1.3)
   933  
   934  	p.updateState()
   935  }
   936  
   937  // StartSneaking makes a player start sneaking. If the player is already sneaking, StartSneaking will not do
   938  // anything.
   939  // If the player is sprinting while StartSneaking is called, the sprinting is stopped.
   940  func (p *Player) StartSneaking() {
   941  	ctx := event.C()
   942  	if p.Handler().HandleToggleSneak(ctx, true); ctx.Cancelled() {
   943  		return
   944  	}
   945  	if !p.sneaking.CAS(false, true) {
   946  		return
   947  	}
   948  	if !p.Flying() {
   949  		p.StopSprinting()
   950  	}
   951  	p.updateState()
   952  }
   953  
   954  // Sneaking checks if the player is currently sneaking.
   955  func (p *Player) Sneaking() bool {
   956  	return p.sneaking.Load()
   957  }
   958  
   959  // StopSneaking makes a player stop sneaking if it currently is. If the player is not sneaking, StopSneaking
   960  // will not do anything.
   961  func (p *Player) StopSneaking() {
   962  	ctx := event.C()
   963  	if p.Handler().HandleToggleSneak(ctx, false); ctx.Cancelled() {
   964  		return
   965  	}
   966  	if !p.sneaking.CAS(true, false) {
   967  		return
   968  	}
   969  	p.updateState()
   970  }
   971  
   972  // StartSwimming makes the player start swimming if it is not currently doing so. If the player is sneaking
   973  // while StartSwimming is called, the sneaking is stopped.
   974  func (p *Player) StartSwimming() {
   975  	if !p.swimming.CAS(false, true) {
   976  		return
   977  	}
   978  	p.StopSneaking()
   979  	p.updateState()
   980  }
   981  
   982  // Swimming checks if the player is currently swimming.
   983  func (p *Player) Swimming() bool {
   984  	return p.swimming.Load()
   985  }
   986  
   987  // StopSwimming makes the player stop swimming if it is currently doing so.
   988  func (p *Player) StopSwimming() {
   989  	if !p.swimming.CAS(true, false) {
   990  		return
   991  	}
   992  	p.updateState()
   993  }
   994  
   995  // StartGliding makes the player start gliding if it is not currently doing so.
   996  func (p *Player) StartGliding() {
   997  	if !p.gliding.CAS(false, true) {
   998  		return
   999  	}
  1000  	chest := p.Armour().Chestplate()
  1001  	if _, ok := chest.Item().(item.Elytra); !ok || chest.Durability() < 2 {
  1002  		return
  1003  	}
  1004  	p.updateState()
  1005  }
  1006  
  1007  // Gliding checks if the player is currently gliding.
  1008  func (p *Player) Gliding() bool {
  1009  	return p.gliding.Load()
  1010  }
  1011  
  1012  // StopGliding makes the player stop gliding if it is currently doing so.
  1013  func (p *Player) StopGliding() {
  1014  	if !p.gliding.CAS(true, false) {
  1015  		return
  1016  	}
  1017  	p.glideTicks.Store(0)
  1018  	p.updateState()
  1019  }
  1020  
  1021  // StartFlying makes the player start flying if they aren't already. It requires the player to be in a gamemode which
  1022  // allows flying.
  1023  func (p *Player) StartFlying() {
  1024  	if !p.GameMode().AllowsFlying() || !p.flying.CAS(false, true) {
  1025  		return
  1026  	}
  1027  	p.session().SendGameMode(p.GameMode())
  1028  }
  1029  
  1030  // Flying checks if the player is currently flying.
  1031  func (p *Player) Flying() bool {
  1032  	return p.flying.Load()
  1033  }
  1034  
  1035  // StopFlying makes the player stop flying if it currently is.
  1036  func (p *Player) StopFlying() {
  1037  	if !p.flying.CAS(true, false) {
  1038  		return
  1039  	}
  1040  	p.session().SendGameMode(p.GameMode())
  1041  }
  1042  
  1043  // Jump makes the player jump if they are on ground. It exhausts the player by 0.05 food points, an additional 0.15
  1044  // is exhausted if the player is sprint jumping.
  1045  func (p *Player) Jump() {
  1046  	if p.Dead() {
  1047  		return
  1048  	}
  1049  
  1050  	p.Handler().HandleJump()
  1051  	if p.OnGround() {
  1052  		jumpVel := 0.42
  1053  		if e, ok := p.Effect(effect.JumpBoost{}); ok {
  1054  			jumpVel = float64(e.Level()) / 10
  1055  		}
  1056  		p.vel.Store(mgl64.Vec3{0, jumpVel})
  1057  	}
  1058  	if p.Sprinting() {
  1059  		p.Exhaust(0.2)
  1060  	} else {
  1061  		p.Exhaust(0.05)
  1062  	}
  1063  }
  1064  
  1065  // SetInvisible sets the player invisible, so that other players will not be able to see it.
  1066  func (p *Player) SetInvisible() {
  1067  	if !p.invisible.CAS(false, true) {
  1068  		return
  1069  	}
  1070  	p.updateState()
  1071  }
  1072  
  1073  // SetVisible sets the player visible again, so that other players can see it again. If the player was already
  1074  // visible, or if the player is in spectator mode, nothing happens.
  1075  func (p *Player) SetVisible() {
  1076  	if !p.GameMode().Visible() {
  1077  		return
  1078  	}
  1079  	if _, ok := p.Effect(effect.Invisibility{}); ok {
  1080  		return
  1081  	}
  1082  	if !p.invisible.CAS(true, false) {
  1083  		return
  1084  	}
  1085  	p.updateState()
  1086  }
  1087  
  1088  // Invisible checks if the Player is currently invisible.
  1089  func (p *Player) Invisible() bool {
  1090  	return p.invisible.Load()
  1091  }
  1092  
  1093  // SetImmobile prevents the player from moving around, but still allows them to look around.
  1094  func (p *Player) SetImmobile() {
  1095  	if !p.immobile.CAS(false, true) {
  1096  		return
  1097  	}
  1098  	p.updateState()
  1099  }
  1100  
  1101  // SetMobile allows the player to freely move around again after being immobile.
  1102  func (p *Player) SetMobile() {
  1103  	if !p.immobile.CAS(true, false) {
  1104  		return
  1105  	}
  1106  	p.updateState()
  1107  }
  1108  
  1109  // Immobile checks if the Player is currently immobile.
  1110  func (p *Player) Immobile() bool {
  1111  	return p.immobile.Load()
  1112  }
  1113  
  1114  // FireProof checks if the Player is currently fireproof. True is returned if the player has a FireResistance effect or
  1115  // if it is in creative mode.
  1116  func (p *Player) FireProof() bool {
  1117  	if _, ok := p.Effect(effect.FireResistance{}); ok {
  1118  		return true
  1119  	}
  1120  	return !p.GameMode().AllowsTakingDamage()
  1121  }
  1122  
  1123  // OnFireDuration ...
  1124  func (p *Player) OnFireDuration() time.Duration {
  1125  	return time.Duration(p.fireTicks.Load()) * time.Second / 20
  1126  }
  1127  
  1128  // SetOnFire ...
  1129  func (p *Player) SetOnFire(duration time.Duration) {
  1130  	ticks := int64(duration.Seconds() * 20)
  1131  	if level := p.Armour().HighestEnchantmentLevel(enchantment.FireProtection{}); level > 0 {
  1132  		ticks -= int64(math.Floor(float64(ticks) * float64(level) * 0.15))
  1133  	}
  1134  	p.fireTicks.Store(ticks)
  1135  	p.updateState()
  1136  }
  1137  
  1138  // Extinguish ...
  1139  func (p *Player) Extinguish() {
  1140  	p.SetOnFire(0)
  1141  }
  1142  
  1143  // Inventory returns the inventory of the player. This inventory holds the items stored in the normal part of
  1144  // the inventory and the hotbar. It also includes the item in the main hand as returned by Player.HeldItems().
  1145  func (p *Player) Inventory() *inventory.Inventory {
  1146  	return p.inv
  1147  }
  1148  
  1149  // Armour returns the armour inventory of the player. This inventory yields 4 slots, for the helmet,
  1150  // chestplate, leggings and boots respectively.
  1151  func (p *Player) Armour() *inventory.Armour {
  1152  	return p.armour
  1153  }
  1154  
  1155  // HeldItems returns the items currently held in the hands of the player. The first item stack returned is the
  1156  // one held in the main hand, the second is held in the off-hand.
  1157  // If no item was held in a hand, the stack returned has a count of 0. Stack.Empty() may be used to check if
  1158  // the hand held anything.
  1159  func (p *Player) HeldItems() (mainHand, offHand item.Stack) {
  1160  	offHand, _ = p.offHand.Item(0)
  1161  	mainHand, _ = p.inv.Item(int(p.heldSlot.Load()))
  1162  	return mainHand, offHand
  1163  }
  1164  
  1165  // SetHeldItems sets items to the main hand and the off-hand of the player. The Stacks passed may be empty
  1166  // (Stack.Empty()) to clear the held item.
  1167  func (p *Player) SetHeldItems(mainHand, offHand item.Stack) {
  1168  	_ = p.inv.SetItem(int(p.heldSlot.Load()), mainHand)
  1169  	_ = p.offHand.SetItem(0, offHand)
  1170  }
  1171  
  1172  // EnderChestInventory returns the player's ender chest inventory. Its accessed by the player when opening
  1173  // ender chests anywhere.
  1174  func (p *Player) EnderChestInventory() *inventory.Inventory {
  1175  	return p.enderChest
  1176  }
  1177  
  1178  // SetGameMode sets the game mode of a player. The game mode specifies the way that the player can interact
  1179  // with the world that it is in.
  1180  func (p *Player) SetGameMode(mode world.GameMode) {
  1181  	previous := p.gameMode.Swap(mode)
  1182  	p.session().SendGameMode(mode)
  1183  	for _, v := range p.viewers() {
  1184  		v.ViewEntityGameMode(p)
  1185  	}
  1186  
  1187  	if !mode.AllowsFlying() {
  1188  		p.StopFlying()
  1189  	}
  1190  	if !mode.Visible() {
  1191  		p.SetInvisible()
  1192  	} else if !previous.Visible() {
  1193  		p.SetVisible()
  1194  	}
  1195  }
  1196  
  1197  // GameMode returns the current game mode assigned to the player. If not changed, the game mode returned will
  1198  // be the same as that of the world that the player spawns in.
  1199  // The game mode may be changed using Player.SetGameMode().
  1200  func (p *Player) GameMode() world.GameMode {
  1201  	return p.gameMode.Load()
  1202  }
  1203  
  1204  // HasCooldown returns true if the item passed has an active cooldown, meaning it currently cannot be used again. If the
  1205  // world.Item passed is nil, HasCooldown always returns false.
  1206  func (p *Player) HasCooldown(item world.Item) bool {
  1207  	if item == nil {
  1208  		return false
  1209  	}
  1210  	p.cooldownMu.Lock()
  1211  	defer p.cooldownMu.Unlock()
  1212  
  1213  	name, _ := item.EncodeItem()
  1214  	otherTime, ok := p.cooldowns[name]
  1215  	if !ok {
  1216  		return false
  1217  	}
  1218  	if time.Now().After(otherTime) {
  1219  		delete(p.cooldowns, name)
  1220  		return false
  1221  	}
  1222  	return true
  1223  }
  1224  
  1225  // SetCooldown sets a cooldown for an item. If the world.Item passed is nil, nothing happens.
  1226  func (p *Player) SetCooldown(item world.Item, cooldown time.Duration) {
  1227  	if item == nil {
  1228  		return
  1229  	}
  1230  	p.cooldownMu.Lock()
  1231  	defer p.cooldownMu.Unlock()
  1232  
  1233  	name, _ := item.EncodeItem()
  1234  	p.cooldowns[name] = time.Now().Add(cooldown)
  1235  	p.session().ViewItemCooldown(item, cooldown)
  1236  }
  1237  
  1238  // UseItem uses the item currently held in the player's main hand in the air. Generally, nothing happens,
  1239  // unless the held item implements the item.Usable interface, in which case it will be activated.
  1240  // This generally happens for items such as throwable items like snowballs.
  1241  func (p *Player) UseItem() {
  1242  	var (
  1243  		i, left = p.HeldItems()
  1244  		w       = p.World()
  1245  		ctx     = event.C()
  1246  	)
  1247  	if p.HasCooldown(i.Item()) {
  1248  		return
  1249  	}
  1250  	if p.Handler().HandleItemUse(ctx); ctx.Cancelled() {
  1251  		return
  1252  	}
  1253  	i, left = p.HeldItems()
  1254  	it := i.Item()
  1255  
  1256  	if cd, ok := it.(item.Cooldown); ok {
  1257  		p.SetCooldown(it, cd.Cooldown())
  1258  	}
  1259  
  1260  	if _, ok := it.(item.Releasable); ok {
  1261  		if !p.canRelease() {
  1262  			return
  1263  		}
  1264  		p.usingSince.Store(time.Now().UnixNano())
  1265  		p.usingItem.Store(true)
  1266  		p.updateState()
  1267  	}
  1268  
  1269  	switch usable := it.(type) {
  1270  	case item.Usable:
  1271  		useCtx := p.useContext()
  1272  		if !usable.Use(w, p, useCtx) {
  1273  			return
  1274  		}
  1275  		// We only swing the player's arm if the item held actually does something. If it doesn't, there is no
  1276  		// reason to swing the arm.
  1277  		p.SwingArm()
  1278  		p.SetHeldItems(p.subtractItem(p.damageItem(i, useCtx.Damage), useCtx.CountSub), left)
  1279  		p.addNewItem(useCtx)
  1280  	case item.Consumable:
  1281  		if c, ok := usable.(interface{ CanConsume() bool }); ok && !c.CanConsume() {
  1282  			p.ReleaseItem()
  1283  			return
  1284  		}
  1285  		if !usable.AlwaysConsumable() && p.GameMode().AllowsTakingDamage() && p.Food() >= 20 {
  1286  			// The item.Consumable is not always consumable, the player is not in creative mode and the
  1287  			// food bar is filled: The item cannot be consumed.
  1288  			p.ReleaseItem()
  1289  			return
  1290  		}
  1291  		if p.usingItem.CAS(false, true) {
  1292  			// Consumable starts being consumed: Set the start timestamp and update the using state to viewers.
  1293  			p.usingSince.Store(time.Now().UnixNano())
  1294  			p.updateState()
  1295  			return
  1296  		}
  1297  		// The player is currently using the item held. This is a signal the item was consumed, so we
  1298  		// consume it and start using it again.
  1299  		p.ReleaseItem()
  1300  		if duration := p.useDuration(); duration < usable.ConsumeDuration() {
  1301  			// The required duration for consuming this item was not met, so we don't consume it.
  1302  			return
  1303  		}
  1304  
  1305  		ctx = event.C()
  1306  		if p.Handler().HandleItemConsume(ctx, i); ctx.Cancelled() {
  1307  			// Consuming was cancelled, but the client will continue consuming the next item.
  1308  			p.usingSince.Store(time.Now().UnixNano())
  1309  			return
  1310  		}
  1311  		p.SetHeldItems(p.subtractItem(i, 1), left)
  1312  
  1313  		useCtx := p.useContext()
  1314  		useCtx.NewItem = usable.Consume(w, p)
  1315  		p.addNewItem(useCtx)
  1316  		w.PlaySound(p.Position().Add(mgl64.Vec3{0, 1.5}), sound.Burp{})
  1317  	}
  1318  }
  1319  
  1320  // ReleaseItem makes the Player release the item it is currently using. This is only applicable for items that
  1321  // implement the item.Releasable interface.
  1322  // If the Player is not currently using any item, ReleaseItem returns immediately.
  1323  // ReleaseItem either aborts the using of the item or finished it, depending on the time that elapsed since
  1324  // the item started being used.
  1325  func (p *Player) ReleaseItem() {
  1326  	if !p.usingItem.CAS(true, false) || !p.canRelease() || !p.GameMode().AllowsInteraction() {
  1327  		return
  1328  	}
  1329  	ctx := p.useContext()
  1330  	i, _ := p.HeldItems()
  1331  	i.Item().(item.Releasable).Release(p, p.useDuration(), ctx)
  1332  
  1333  	p.handleUseContext(ctx)
  1334  	p.updateState()
  1335  }
  1336  
  1337  // canRelease returns whether the player can release the item currently held in the main hand.
  1338  func (p *Player) canRelease() bool {
  1339  	held, _ := p.HeldItems()
  1340  	releasable, ok := held.Item().(item.Releasable)
  1341  	if !ok {
  1342  		return false
  1343  	}
  1344  	if p.GameMode().CreativeInventory() {
  1345  		return true
  1346  	}
  1347  	for _, req := range releasable.Requirements() {
  1348  		_, found := p.Inventory().FirstFunc(func(stack item.Stack) bool {
  1349  			name, _ := stack.Item().EncodeItem()
  1350  			otherName, _ := req.Item().EncodeItem()
  1351  			return name == otherName
  1352  		})
  1353  		if !found {
  1354  			return false
  1355  		}
  1356  	}
  1357  	return true
  1358  }
  1359  
  1360  // handleUseContext handles the item.UseContext after the item has been used.
  1361  func (p *Player) handleUseContext(ctx *item.UseContext) {
  1362  	i, left := p.HeldItems()
  1363  
  1364  	p.SetHeldItems(p.subtractItem(p.damageItem(i, ctx.Damage), ctx.CountSub), left)
  1365  	p.addNewItem(ctx)
  1366  	for _, it := range ctx.ConsumedItems {
  1367  		_ = p.Inventory().RemoveItem(it)
  1368  	}
  1369  }
  1370  
  1371  // useDuration returns the duration the player has been using the item in the main hand.
  1372  func (p *Player) useDuration() time.Duration {
  1373  	return time.Duration(time.Now().UnixNano()-p.usingSince.Load()) + time.Second/20
  1374  }
  1375  
  1376  // UsingItem checks if the Player is currently using an item. True is returned if the Player is currently eating an
  1377  // item or using it over a longer duration such as when using a bow.
  1378  func (p *Player) UsingItem() bool {
  1379  	return p.usingItem.Load()
  1380  }
  1381  
  1382  // UseItemOnBlock uses the item held in the main hand of the player on a block at the position passed. The
  1383  // player is assumed to have clicked the face passed with the relative click position clickPos.
  1384  // If the item could not be used successfully, for example when the position is out of range, the method
  1385  // returns immediately.
  1386  // UseItemOnBlock does nothing if the block at the cube.Pos passed is of the type block.Air.
  1387  func (p *Player) UseItemOnBlock(pos cube.Pos, face cube.Face, clickPos mgl64.Vec3) {
  1388  	w := p.World()
  1389  	if _, ok := w.Block(pos).(block.Air); ok || !p.canReach(pos.Vec3Centre()) {
  1390  		// The client used its item on a block that does not exist server-side or one it couldn't reach. Stop trying
  1391  		// to use the item immediately.
  1392  		p.resendBlocks(pos, w, face)
  1393  		return
  1394  	}
  1395  	ctx := event.C()
  1396  	if p.Handler().HandleItemUseOnBlock(ctx, pos, face, clickPos); ctx.Cancelled() {
  1397  		p.resendBlocks(pos, w, face)
  1398  		return
  1399  	}
  1400  	i, left := p.HeldItems()
  1401  	b := w.Block(pos)
  1402  	if act, ok := b.(block.Activatable); ok {
  1403  		// If a player is sneaking, it will not activate the block clicked, unless it is not holding any
  1404  		// items, in which case the block will be activated as usual.
  1405  		if !p.Sneaking() || i.Empty() {
  1406  			p.SwingArm()
  1407  
  1408  			// The block was activated: Blocks such as doors must always have precedence over the item being
  1409  			// used.
  1410  			if useCtx := p.useContext(); act.Activate(pos, face, p.World(), p, useCtx) {
  1411  				p.SetHeldItems(p.subtractItem(p.damageItem(i, useCtx.Damage), useCtx.CountSub), left)
  1412  				p.addNewItem(useCtx)
  1413  				return
  1414  			}
  1415  		}
  1416  	}
  1417  	if i.Empty() {
  1418  		return
  1419  	}
  1420  	switch ib := i.Item().(type) {
  1421  	case item.UsableOnBlock:
  1422  		// The item does something when used on a block.
  1423  		useCtx := p.useContext()
  1424  		if !ib.UseOnBlock(pos, face, clickPos, p.World(), p, useCtx) {
  1425  			return
  1426  		}
  1427  		p.SwingArm()
  1428  		p.SetHeldItems(p.subtractItem(p.damageItem(i, useCtx.Damage), useCtx.CountSub), left)
  1429  		p.addNewItem(useCtx)
  1430  	case world.Block:
  1431  		// The item IS a block, meaning it is being placed.
  1432  		replacedPos := pos
  1433  		if replaceable, ok := b.(block.Replaceable); !ok || !replaceable.ReplaceableBy(ib) {
  1434  			// The block clicked was either not replaceable, or not replaceable using the block passed.
  1435  			replacedPos = pos.Side(face)
  1436  		}
  1437  		if replaceable, ok := w.Block(replacedPos).(block.Replaceable); !ok || !replaceable.ReplaceableBy(ib) || replacedPos.OutOfBounds(w.Range()) {
  1438  			return
  1439  		}
  1440  		if !p.placeBlock(replacedPos, ib, false) || p.GameMode().CreativeInventory() {
  1441  			return
  1442  		}
  1443  		p.SetHeldItems(p.subtractItem(i, 1), left)
  1444  	}
  1445  }
  1446  
  1447  // UseItemOnEntity uses the item held in the main hand of the player on the entity passed, provided it is
  1448  // within range of the player.
  1449  // If the item held in the main hand of the player does nothing when used on an entity, nothing will happen.
  1450  func (p *Player) UseItemOnEntity(e world.Entity) bool {
  1451  	if !p.canReach(e.Position()) {
  1452  		return false
  1453  	}
  1454  	ctx := event.C()
  1455  	if p.Handler().HandleItemUseOnEntity(ctx, e); ctx.Cancelled() {
  1456  		return false
  1457  	}
  1458  	i, left := p.HeldItems()
  1459  	usable, ok := i.Item().(item.UsableOnEntity)
  1460  	if !ok {
  1461  		return true
  1462  	}
  1463  	useCtx := p.useContext()
  1464  	if !usable.UseOnEntity(e, e.World(), p, useCtx) {
  1465  		return true
  1466  	}
  1467  	p.SwingArm()
  1468  	p.SetHeldItems(p.subtractItem(p.damageItem(i, useCtx.Damage), useCtx.CountSub), left)
  1469  	p.addNewItem(useCtx)
  1470  	return true
  1471  }
  1472  
  1473  // AttackEntity uses the item held in the main hand of the player to attack the entity passed, provided it is
  1474  // within range of the player.
  1475  // The damage dealt to the entity will depend on the item held by the player and any effects the player may
  1476  // have.
  1477  // If the player cannot reach the entity at its position, the method returns immediately.
  1478  func (p *Player) AttackEntity(e world.Entity) bool {
  1479  	if !p.canReach(e.Position()) {
  1480  		return false
  1481  	}
  1482  	var (
  1483  		force, height  = 0.45, 0.3608
  1484  		_, slowFalling = p.Effect(effect.SlowFalling{})
  1485  		_, blind       = p.Effect(effect.Blindness{})
  1486  		critical       = !p.Sprinting() && !p.Flying() && p.FallDistance() > 0 && !slowFalling && !blind
  1487  	)
  1488  
  1489  	ctx := event.C()
  1490  	if p.Handler().HandleAttackEntity(ctx, e, &force, &height, &critical); ctx.Cancelled() {
  1491  		return false
  1492  	}
  1493  	p.SwingArm()
  1494  
  1495  	i, _ := p.HeldItems()
  1496  	living, ok := e.(entity.Living)
  1497  	if !ok {
  1498  		return false
  1499  	}
  1500  	if living.AttackImmune() {
  1501  		return true
  1502  	}
  1503  
  1504  	dmg := i.AttackDamage()
  1505  	if strength, ok := p.Effect(effect.Strength{}); ok {
  1506  		dmg += dmg * effect.Strength{}.Multiplier(strength.Level())
  1507  	}
  1508  	if weakness, ok := p.Effect(effect.Weakness{}); ok {
  1509  		dmg -= dmg * effect.Weakness{}.Multiplier(weakness.Level())
  1510  	}
  1511  	if s, ok := i.Enchantment(enchantment.Sharpness{}); ok {
  1512  		dmg += (enchantment.Sharpness{}).Addend(s.Level())
  1513  	}
  1514  	if critical {
  1515  		dmg *= 1.5
  1516  	}
  1517  
  1518  	n, vulnerable := living.Hurt(dmg, entity.AttackDamageSource{Attacker: p})
  1519  	i, left := p.HeldItems()
  1520  
  1521  	p.World().PlaySound(entity.EyePosition(e), sound.Attack{Damage: !mgl64.FloatEqual(n, 0)})
  1522  	if !vulnerable {
  1523  		return true
  1524  	}
  1525  	if critical {
  1526  		for _, v := range p.World().Viewers(living.Position()) {
  1527  			v.ViewEntityAction(living, entity.CriticalHitAction{})
  1528  		}
  1529  	}
  1530  
  1531  	p.Exhaust(0.1)
  1532  
  1533  	if k, ok := i.Enchantment(enchantment.KnockBack{}); ok {
  1534  		inc := (enchantment.KnockBack{}).Force(k.Level())
  1535  		force += inc
  1536  		height += inc
  1537  	}
  1538  	living.KnockBack(p.Position(), force, height)
  1539  
  1540  	if f, ok := i.Enchantment(enchantment.FireAspect{}); ok {
  1541  		if flammable, ok := living.(entity.Flammable); ok {
  1542  			flammable.SetOnFire((enchantment.FireAspect{}).Duration(f.Level()))
  1543  		}
  1544  	}
  1545  
  1546  	if durable, ok := i.Item().(item.Durable); ok {
  1547  		p.SetHeldItems(p.damageItem(i, durable.DurabilityInfo().AttackDurability), left)
  1548  	}
  1549  	return true
  1550  }
  1551  
  1552  // StartBreaking makes the player start breaking the block at the position passed using the item currently
  1553  // held in its main hand.
  1554  // If no block is present at the position, or if the block is out of range, StartBreaking will return
  1555  // immediately and the block will not be broken. StartBreaking will stop the breaking of any block that the
  1556  // player might be breaking before this method is called.
  1557  func (p *Player) StartBreaking(pos cube.Pos, face cube.Face) {
  1558  	p.AbortBreaking()
  1559  	w := p.World()
  1560  	if _, air := w.Block(pos).(block.Air); air || !p.canReach(pos.Vec3Centre()) {
  1561  		// The block was either out of range or air, so it can't be broken by the player.
  1562  		return
  1563  	}
  1564  	if _, ok := w.Block(pos.Side(face)).(block.Fire); ok {
  1565  		// TODO: Add a way to cancel fire extinguishing. This is currently not possible to handle.
  1566  		w.SetBlock(pos.Side(face), nil, nil)
  1567  		w.PlaySound(pos.Vec3(), sound.FireExtinguish{})
  1568  		return
  1569  	}
  1570  
  1571  	held, _ := p.HeldItems()
  1572  	if _, ok := held.Item().(item.Sword); ok && p.GameMode().CreativeInventory() {
  1573  		// Can't break blocks with a sword in creative mode.
  1574  		return
  1575  	}
  1576  	// Note: We intentionally store this regardless of whether the breaking proceeds, so that we
  1577  	// can resend the block to the client when it tries to break the block regardless.
  1578  	p.breakingPos.Store(pos)
  1579  
  1580  	ctx := event.C()
  1581  	if p.Handler().HandleStartBreak(ctx, pos); ctx.Cancelled() {
  1582  		return
  1583  	}
  1584  	if punchable, ok := w.Block(pos).(block.Punchable); ok {
  1585  		punchable.Punch(pos, face, w, p)
  1586  	}
  1587  
  1588  	p.breaking.Store(true)
  1589  	p.SwingArm()
  1590  
  1591  	if p.GameMode().CreativeInventory() {
  1592  		return
  1593  	}
  1594  	p.lastBreakDuration = p.breakTime(pos)
  1595  	for _, viewer := range p.viewers() {
  1596  		viewer.ViewBlockAction(pos, block.StartCrackAction{BreakTime: p.lastBreakDuration})
  1597  	}
  1598  }
  1599  
  1600  // breakTime returns the time needed to break a block at the position passed, taking into account the item
  1601  // held, if the player is on the ground/underwater and if the player has any effects.
  1602  func (p *Player) breakTime(pos cube.Pos) time.Duration {
  1603  	held, _ := p.HeldItems()
  1604  	w := p.World()
  1605  	breakTime := block.BreakDuration(w.Block(pos), held)
  1606  	if !p.OnGround() {
  1607  		breakTime *= 5
  1608  	}
  1609  	if _, ok := p.Armour().Helmet().Enchantment(enchantment.AquaAffinity{}); p.insideOfWater(w) && !ok {
  1610  		breakTime *= 5
  1611  	}
  1612  	for _, e := range p.Effects() {
  1613  		lvl := e.Level()
  1614  		switch v := e.Type().(type) {
  1615  		case effect.Haste:
  1616  			breakTime = time.Duration(float64(breakTime) * v.Multiplier(lvl))
  1617  		case effect.MiningFatigue:
  1618  			breakTime = time.Duration(float64(breakTime) * v.Multiplier(lvl))
  1619  		case effect.ConduitPower:
  1620  			breakTime = time.Duration(float64(breakTime) * v.Multiplier(lvl))
  1621  		}
  1622  	}
  1623  	return breakTime
  1624  }
  1625  
  1626  // FinishBreaking makes the player finish breaking the block it is currently breaking, or returns immediately
  1627  // if the player isn't breaking anything.
  1628  // FinishBreaking will stop the animation and break the block.
  1629  func (p *Player) FinishBreaking() {
  1630  	pos := p.breakingPos.Load()
  1631  	if !p.breaking.Load() {
  1632  		p.resendBlock(pos, p.World())
  1633  		return
  1634  	}
  1635  	p.AbortBreaking()
  1636  	p.BreakBlock(pos)
  1637  }
  1638  
  1639  // AbortBreaking makes the player stop breaking the block it is currently breaking, or returns immediately
  1640  // if the player isn't breaking anything.
  1641  // Unlike FinishBreaking, AbortBreaking does not stop the animation.
  1642  func (p *Player) AbortBreaking() {
  1643  	if !p.breaking.CAS(true, false) {
  1644  		return
  1645  	}
  1646  	p.breakParticleCounter.Store(0)
  1647  	pos := p.breakingPos.Load()
  1648  	for _, viewer := range p.viewers() {
  1649  		viewer.ViewBlockAction(pos, block.StopCrackAction{})
  1650  	}
  1651  }
  1652  
  1653  // ContinueBreaking makes the player continue breaking the block it started breaking after a call to
  1654  // Player.StartBreaking().
  1655  // The face passed is used to display particles on the side of the block broken.
  1656  func (p *Player) ContinueBreaking(face cube.Face) {
  1657  	if !p.breaking.Load() {
  1658  		return
  1659  	}
  1660  	pos := p.breakingPos.Load()
  1661  
  1662  	p.SwingArm()
  1663  
  1664  	w := p.World()
  1665  	b := w.Block(pos)
  1666  	w.AddParticle(pos.Vec3(), particle.PunchBlock{Block: b, Face: face})
  1667  
  1668  	if p.breakParticleCounter.Add(1)%5 == 0 {
  1669  		// We send this sound only every so often. Vanilla doesn't send it every tick while breaking
  1670  		// either. Every 5 ticks seems accurate.
  1671  		w.PlaySound(pos.Vec3(), sound.BlockBreaking{Block: w.Block(pos)})
  1672  	}
  1673  	breakTime := p.breakTime(pos)
  1674  	if breakTime != p.lastBreakDuration {
  1675  		for _, viewer := range p.viewers() {
  1676  			viewer.ViewBlockAction(pos, block.ContinueCrackAction{BreakTime: breakTime})
  1677  		}
  1678  		p.lastBreakDuration = breakTime
  1679  	}
  1680  }
  1681  
  1682  // PlaceBlock makes the player place the block passed at the position passed, granted it is within the range
  1683  // of the player.
  1684  // An item.UseContext may be passed to obtain information on if the block placement was successful. (SubCount will
  1685  // be incremented). Nil may also be passed for the context parameter.
  1686  func (p *Player) PlaceBlock(pos cube.Pos, b world.Block, ctx *item.UseContext) {
  1687  	if !p.placeBlock(pos, b, ctx.IgnoreBBox) {
  1688  		return
  1689  	}
  1690  	if ctx != nil {
  1691  		ctx.CountSub++
  1692  	}
  1693  }
  1694  
  1695  // placeBlock makes the player place the block passed at the position passed, granted it is within the range
  1696  // of the player. A bool is returned indicating if a block was placed successfully.
  1697  func (p *Player) placeBlock(pos cube.Pos, b world.Block, ignoreBBox bool) bool {
  1698  	w := p.World()
  1699  	if !p.canReach(pos.Vec3Centre()) || !p.GameMode().AllowsEditing() {
  1700  		p.resendBlocks(pos, w, cube.Faces()...)
  1701  		return false
  1702  	}
  1703  	if !ignoreBBox && p.obstructedPos(pos, b) {
  1704  		p.resendBlocks(pos, w, cube.Faces()...)
  1705  		return false
  1706  	}
  1707  
  1708  	ctx := event.C()
  1709  	if p.Handler().HandleBlockPlace(ctx, pos, b); ctx.Cancelled() {
  1710  		p.resendBlocks(pos, w, cube.Faces()...)
  1711  		return false
  1712  	}
  1713  	w.SetBlock(pos, b, nil)
  1714  	w.PlaySound(pos.Vec3(), sound.BlockPlace{Block: b})
  1715  	p.SwingArm()
  1716  	return true
  1717  }
  1718  
  1719  // obstructedPos checks if the position passed is obstructed if the block passed is attempted to be placed.
  1720  // The function returns true if there is an entity in the way that could prevent the block from being placed.
  1721  func (p *Player) obstructedPos(pos cube.Pos, b world.Block) bool {
  1722  	w := p.World()
  1723  	blockBoxes := b.Model().BBox(pos, w)
  1724  	for i, box := range blockBoxes {
  1725  		blockBoxes[i] = box.Translate(pos.Vec3())
  1726  	}
  1727  
  1728  	around := w.EntitiesWithin(cube.Box(-3, -3, -3, 3, 3, 3).Translate(pos.Vec3()), nil)
  1729  	for _, e := range around {
  1730  		switch e.Type().(type) {
  1731  		case entity.ItemType, entity.ArrowType:
  1732  			continue
  1733  		default:
  1734  			if cube.AnyIntersections(blockBoxes, e.Type().BBox(e).Translate(e.Position()).Grow(-1e-6)) {
  1735  				return true
  1736  			}
  1737  		}
  1738  	}
  1739  	return false
  1740  }
  1741  
  1742  // BreakBlock makes the player break a block in the world at a position passed. If the player is unable to
  1743  // reach the block passed, the method returns immediately.
  1744  func (p *Player) BreakBlock(pos cube.Pos) {
  1745  	w := p.World()
  1746  	b := w.Block(pos)
  1747  	if _, air := b.(block.Air); air {
  1748  		// Don't do anything if the position broken is already air.
  1749  		return
  1750  	}
  1751  	if !p.canReach(pos.Vec3Centre()) || !p.GameMode().AllowsEditing() {
  1752  		p.resendBlocks(pos, w)
  1753  		return
  1754  	}
  1755  	if _, breakable := b.(block.Breakable); !breakable && !p.GameMode().CreativeInventory() {
  1756  		p.resendBlocks(pos, w)
  1757  		return
  1758  	}
  1759  	held, _ := p.HeldItems()
  1760  	drops := p.drops(held, b)
  1761  
  1762  	xp := 0
  1763  	if breakable, ok := b.(block.Breakable); ok && !p.GameMode().CreativeInventory() {
  1764  		xp = breakable.BreakInfo().XPDrops.RandomValue()
  1765  	}
  1766  
  1767  	ctx := event.C()
  1768  	if p.Handler().HandleBlockBreak(ctx, pos, &drops, &xp); ctx.Cancelled() {
  1769  		p.resendBlocks(pos, w)
  1770  		return
  1771  	}
  1772  	held, left := p.HeldItems()
  1773  
  1774  	p.SwingArm()
  1775  	w.SetBlock(pos, nil, nil)
  1776  	w.AddParticle(pos.Vec3Centre(), particle.BlockBreak{Block: b})
  1777  
  1778  	if breakable, ok := b.(block.Breakable); ok {
  1779  		info := breakable.BreakInfo()
  1780  		if info.BreakHandler != nil {
  1781  			info.BreakHandler(pos, w, p)
  1782  		}
  1783  		for _, orb := range entity.NewExperienceOrbs(pos.Vec3Centre(), xp) {
  1784  			orb.SetVelocity(mgl64.Vec3{(rand.Float64()*0.2 - 0.1) * 2, rand.Float64() * 0.4, (rand.Float64()*0.2 - 0.1) * 2})
  1785  			w.AddEntity(orb)
  1786  		}
  1787  	}
  1788  	for _, drop := range drops {
  1789  		ent := entity.NewItem(drop, pos.Vec3Centre())
  1790  		ent.SetVelocity(mgl64.Vec3{rand.Float64()*0.2 - 0.1, 0.2, rand.Float64()*0.2 - 0.1})
  1791  		w.AddEntity(ent)
  1792  	}
  1793  
  1794  	p.Exhaust(0.005)
  1795  	if block.BreaksInstantly(b, held) {
  1796  		return
  1797  	}
  1798  	if durable, ok := held.Item().(item.Durable); ok {
  1799  		p.SetHeldItems(p.damageItem(held, durable.DurabilityInfo().BreakDurability), left)
  1800  	}
  1801  }
  1802  
  1803  // drops returns the drops that the player can get from the block passed using the item held.
  1804  func (p *Player) drops(held item.Stack, b world.Block) []item.Stack {
  1805  	t, ok := held.Item().(item.Tool)
  1806  	if !ok {
  1807  		t = item.ToolNone{}
  1808  	}
  1809  	var drops []item.Stack
  1810  	if container, ok := b.(block.Container); ok {
  1811  		// If the block is a container, it should drop its inventory contents regardless whether the
  1812  		// player is in creative mode or not.
  1813  		drops = container.Inventory().Items()
  1814  		if breakable, ok := b.(block.Breakable); ok && !p.GameMode().CreativeInventory() {
  1815  			if breakable.BreakInfo().Harvestable(t) {
  1816  				drops = append(drops, breakable.BreakInfo().Drops(t, held.Enchantments())...)
  1817  			}
  1818  		}
  1819  		container.Inventory().Clear()
  1820  	} else if breakable, ok := b.(block.Breakable); ok && !p.GameMode().CreativeInventory() {
  1821  		if breakable.BreakInfo().Harvestable(t) {
  1822  			drops = breakable.BreakInfo().Drops(t, held.Enchantments())
  1823  		}
  1824  	} else if it, ok := b.(world.Item); ok && !p.GameMode().CreativeInventory() {
  1825  		drops = []item.Stack{item.NewStack(it, 1)}
  1826  	}
  1827  	return drops
  1828  }
  1829  
  1830  // PickBlock makes the player pick a block in the world at a position passed. If the player is unable to
  1831  // pick the block, the method returns immediately.
  1832  func (p *Player) PickBlock(pos cube.Pos) {
  1833  	if !p.canReach(pos.Vec3()) {
  1834  		return
  1835  	}
  1836  
  1837  	b := p.World().Block(pos)
  1838  
  1839  	var pickedItem item.Stack
  1840  	if pi, ok := b.(block.Pickable); ok {
  1841  		pickedItem = pi.Pick()
  1842  	} else if i, ok := b.(world.Item); ok {
  1843  		it, _ := world.ItemByName(i.EncodeItem())
  1844  		pickedItem = item.NewStack(it, 1)
  1845  	} else {
  1846  		return
  1847  	}
  1848  
  1849  	slot, found := p.Inventory().First(pickedItem)
  1850  	if !found && !p.GameMode().CreativeInventory() {
  1851  		return
  1852  	}
  1853  
  1854  	ctx := event.C()
  1855  	if p.Handler().HandleBlockPick(ctx, pos, b); ctx.Cancelled() {
  1856  		return
  1857  	}
  1858  	_, offhand := p.HeldItems()
  1859  
  1860  	if found {
  1861  		if slot < 9 {
  1862  			_ = p.session().SetHeldSlot(slot)
  1863  			return
  1864  		}
  1865  		_ = p.Inventory().Swap(slot, int(p.heldSlot.Load()))
  1866  		return
  1867  	}
  1868  
  1869  	firstEmpty, emptyFound := p.Inventory().FirstEmpty()
  1870  	if !emptyFound {
  1871  		p.SetHeldItems(pickedItem, offhand)
  1872  		return
  1873  	}
  1874  	if firstEmpty < 8 {
  1875  		_ = p.session().SetHeldSlot(firstEmpty)
  1876  		_ = p.Inventory().SetItem(firstEmpty, pickedItem)
  1877  		return
  1878  	}
  1879  	_ = p.Inventory().Swap(firstEmpty, int(p.heldSlot.Load()))
  1880  	p.SetHeldItems(pickedItem, offhand)
  1881  }
  1882  
  1883  // Teleport teleports the player to a target position in the world. Unlike Move, it immediately changes the
  1884  // position of the player, rather than showing an animation.
  1885  func (p *Player) Teleport(pos mgl64.Vec3) {
  1886  	ctx := event.C()
  1887  	if p.Handler().HandleTeleport(ctx, pos); ctx.Cancelled() {
  1888  		return
  1889  	}
  1890  	p.teleport(pos)
  1891  }
  1892  
  1893  // teleport teleports the player to a target position in the world. It does not call the Handler of the
  1894  // player.
  1895  func (p *Player) teleport(pos mgl64.Vec3) {
  1896  	for _, v := range p.viewers() {
  1897  		v.ViewEntityTeleport(p, pos)
  1898  	}
  1899  	p.pos.Store(pos)
  1900  	p.vel.Store(mgl64.Vec3{})
  1901  	p.ResetFallDistance()
  1902  }
  1903  
  1904  // Move moves the player from one position to another in the world, by adding the delta passed to the current
  1905  // position of the player.
  1906  // Move also rotates the player, adding deltaYaw and deltaPitch to the respective values.
  1907  func (p *Player) Move(deltaPos mgl64.Vec3, deltaYaw, deltaPitch float64) {
  1908  	if p.Dead() || (deltaPos.ApproxEqual(mgl64.Vec3{}) && mgl64.FloatEqual(deltaYaw, 0) && mgl64.FloatEqual(deltaPitch, 0)) {
  1909  		return
  1910  	}
  1911  	if p.immobile.Load() {
  1912  		if mgl64.FloatEqual(deltaYaw, 0) && mgl64.FloatEqual(deltaPitch, 0) {
  1913  			// If only the position was changed, don't continue with the movement when immobile.
  1914  			return
  1915  		}
  1916  		// Still update rotation if it was changed.
  1917  		deltaPos = mgl64.Vec3{}
  1918  	}
  1919  	var (
  1920  		w                     = p.World()
  1921  		pos                   = p.Position()
  1922  		yaw, pitch            = p.Rotation().Elem()
  1923  		res, resYaw, resPitch = pos.Add(deltaPos), yaw + deltaYaw, pitch + deltaPitch
  1924  	)
  1925  	ctx := event.C()
  1926  	if p.Handler().HandleMove(ctx, res, resYaw, resPitch); ctx.Cancelled() {
  1927  		if p.session() != session.Nop && pos.ApproxEqual(p.Position()) {
  1928  			// The position of the player was changed and the event cancelled. This means we still need to notify the
  1929  			// player of this movement change.
  1930  			p.teleport(pos)
  1931  		}
  1932  		return
  1933  	}
  1934  	for _, v := range p.viewers() {
  1935  		v.ViewEntityMovement(p, res, cube.Rotation{resYaw, resPitch}, p.OnGround())
  1936  	}
  1937  
  1938  	p.pos.Store(res)
  1939  	p.yaw.Store(resYaw)
  1940  	p.pitch.Store(resPitch)
  1941  	if deltaPos.Len() <= 3 {
  1942  		// Only update velocity if the player is not moving too fast to prevent potential OOMs.
  1943  		p.vel.Store(deltaPos)
  1944  		p.checkBlockCollisions(deltaPos, w)
  1945  	}
  1946  
  1947  	horizontalVel := deltaPos
  1948  	horizontalVel[1] = 0
  1949  	if p.Gliding() {
  1950  		if deltaPos.Y() >= -0.5 {
  1951  			p.fallDistance.Store(1.0)
  1952  		}
  1953  		if p.collidedHorizontally.Load() {
  1954  			if force := horizontalVel.Len()*10.0 - 3.0; force > 0.0 && !p.AttackImmune() {
  1955  				w.PlaySound(p.Position(), sound.Fall{Distance: force})
  1956  				p.Hurt(force, entity.GlideDamageSource{})
  1957  			}
  1958  		}
  1959  	}
  1960  
  1961  	_, submergedBefore := w.Liquid(cube.PosFromVec3(pos.Add(mgl64.Vec3{0, p.EyeHeight()})))
  1962  	_, submergedAfter := w.Liquid(cube.PosFromVec3(res.Add(mgl64.Vec3{0, p.EyeHeight()})))
  1963  	if submergedBefore != submergedAfter {
  1964  		// Player wasn't either breathing before and no longer isn't, or wasn't breathing before and now is,
  1965  		// so send the updated metadata.
  1966  		p.session().ViewEntityState(p)
  1967  	}
  1968  
  1969  	p.onGround.Store(p.checkOnGround(w))
  1970  	p.updateFallState(deltaPos[1])
  1971  
  1972  	if p.Swimming() {
  1973  		p.Exhaust(0.01 * horizontalVel.Len())
  1974  	} else if p.Sprinting() {
  1975  		p.Exhaust(0.1 * horizontalVel.Len())
  1976  	}
  1977  }
  1978  
  1979  // World returns the world that the player is currently in.
  1980  func (p *Player) World() *world.World {
  1981  	w, _ := world.OfEntity(p)
  1982  	return w
  1983  }
  1984  
  1985  // Position returns the current position of the player. It may be changed as the player moves or is moved
  1986  // around the world.
  1987  func (p *Player) Position() mgl64.Vec3 {
  1988  	return p.pos.Load()
  1989  }
  1990  
  1991  // Velocity returns the players current velocity. If there is an attached session, this will be empty.
  1992  func (p *Player) Velocity() mgl64.Vec3 {
  1993  	return p.vel.Load()
  1994  }
  1995  
  1996  // SetVelocity updates the player's velocity. If there is an attached session, this will just send
  1997  // the velocity to the player session for the player to update.
  1998  func (p *Player) SetVelocity(velocity mgl64.Vec3) {
  1999  	if p.session() == session.Nop {
  2000  		p.vel.Store(velocity)
  2001  		return
  2002  	}
  2003  	for _, v := range p.viewers() {
  2004  		v.ViewEntityVelocity(p, velocity)
  2005  	}
  2006  }
  2007  
  2008  // Rotation returns the yaw and pitch of the player in degrees. Yaw is horizontal rotation (rotation around the
  2009  // vertical axis, 0 when facing forward), pitch is vertical rotation (rotation around the horizontal axis, also 0
  2010  // when facing forward).
  2011  func (p *Player) Rotation() cube.Rotation {
  2012  	return cube.Rotation{p.yaw.Load(), p.pitch.Load()}
  2013  }
  2014  
  2015  // Collect makes the player collect the item stack passed, adding it to the inventory. The amount of items that could
  2016  // be added is returned.
  2017  func (p *Player) Collect(s item.Stack) int {
  2018  	if p.Dead() {
  2019  		return 0
  2020  	}
  2021  	if !p.GameMode().AllowsInteraction() {
  2022  		return 0
  2023  	}
  2024  	ctx := event.C()
  2025  	if p.Handler().HandleItemPickup(ctx, &s); ctx.Cancelled() {
  2026  		return 0
  2027  	}
  2028  	n, _ := p.Inventory().AddItem(s)
  2029  	return n
  2030  }
  2031  
  2032  // Experience returns the amount of experience the player has.
  2033  func (p *Player) Experience() int {
  2034  	return p.experience.Experience()
  2035  }
  2036  
  2037  // EnchantmentSeed is a seed used to calculate random enchantments with enchantment tables.
  2038  func (p *Player) EnchantmentSeed() int64 {
  2039  	return p.enchantSeed.Load()
  2040  }
  2041  
  2042  // ResetEnchantmentSeed resets the enchantment seed to a new random value.
  2043  func (p *Player) ResetEnchantmentSeed() {
  2044  	p.enchantSeed.Store(rand.Int63())
  2045  }
  2046  
  2047  // AddExperience adds experience to the player.
  2048  func (p *Player) AddExperience(amount int) int {
  2049  	ctx := event.C()
  2050  	if p.Handler().HandleExperienceGain(ctx, &amount); ctx.Cancelled() {
  2051  		return 0
  2052  	}
  2053  	before := p.experience.Level()
  2054  	level, _ := p.experience.Add(amount)
  2055  	if level/5 > before/5 {
  2056  		p.PlaySound(sound.LevelUp{})
  2057  	} else if amount > 0 {
  2058  		p.PlaySound(sound.Experience{})
  2059  	}
  2060  	p.session().SendExperience(p.experience)
  2061  	return amount
  2062  }
  2063  
  2064  // RemoveExperience removes experience from the player.
  2065  func (p *Player) RemoveExperience(amount int) {
  2066  	p.experience.Add(-amount)
  2067  	p.session().SendExperience(p.experience)
  2068  }
  2069  
  2070  // ExperienceLevel returns the experience level of the player.
  2071  func (p *Player) ExperienceLevel() int {
  2072  	return p.experience.Level()
  2073  }
  2074  
  2075  // SetExperienceLevel sets the experience level of the player. The level must have a value between 0 and 2,147,483,647,
  2076  // otherwise the method panics.
  2077  func (p *Player) SetExperienceLevel(level int) {
  2078  	p.experience.SetLevel(level)
  2079  	p.session().SendExperience(p.experience)
  2080  }
  2081  
  2082  // ExperienceProgress returns the experience progress of the player.
  2083  func (p *Player) ExperienceProgress() float64 {
  2084  	return p.experience.Progress()
  2085  }
  2086  
  2087  // SetExperienceProgress sets the experience progress of the player. The progress must have a value between 0.0 and 1.0, otherwise
  2088  // the method panics.
  2089  func (p *Player) SetExperienceProgress(progress float64) {
  2090  	p.experience.SetProgress(progress)
  2091  	p.session().SendExperience(p.experience)
  2092  }
  2093  
  2094  // CollectExperience makes the player collect the experience points passed, adding it to the experience manager. A bool
  2095  // is returned indicating whether the player was able to collect the experience or not, due to the 100ms delay between
  2096  // experience collection or if the player was dead or in a game mode that doesn't allow collection.
  2097  func (p *Player) CollectExperience(value int) bool {
  2098  	if p.Dead() || !p.GameMode().AllowsInteraction() {
  2099  		return false
  2100  	}
  2101  	if time.Since(p.lastXPPickup.Load()) < time.Millisecond*100 {
  2102  		return false
  2103  	}
  2104  	value = p.mendItems(value)
  2105  	p.lastXPPickup.Store(time.Now())
  2106  	if value > 0 {
  2107  		return p.AddExperience(value) > 0
  2108  	}
  2109  
  2110  	p.PlaySound(sound.Experience{})
  2111  	return true
  2112  }
  2113  
  2114  // mendItems handles the mending enchantment when collecting experience, it then returns the leftover experience.
  2115  func (p *Player) mendItems(xp int) int {
  2116  	mendingItems := make([]item.Stack, 0, 6)
  2117  	held, offHand := p.HeldItems()
  2118  	if _, ok := offHand.Enchantment(enchantment.Mending{}); ok && offHand.Durability() < offHand.MaxDurability() {
  2119  		mendingItems = append(mendingItems, offHand)
  2120  	}
  2121  	if _, ok := held.Enchantment(enchantment.Mending{}); ok && held.Durability() < held.MaxDurability() {
  2122  		mendingItems = append(mendingItems, held)
  2123  	}
  2124  	for _, i := range p.Armour().Items() {
  2125  		if i.Durability() == i.MaxDurability() {
  2126  			continue
  2127  		}
  2128  		if _, ok := i.Enchantment(enchantment.Mending{}); ok {
  2129  			mendingItems = append(mendingItems, i)
  2130  		}
  2131  	}
  2132  	length := len(mendingItems)
  2133  	if length == 0 {
  2134  		return xp
  2135  	}
  2136  	foundItem := mendingItems[rand.Intn(length)]
  2137  	repairAmount := math.Min(float64(foundItem.MaxDurability()-foundItem.Durability()), float64(xp*2))
  2138  	repairedItem := foundItem.WithDurability(foundItem.Durability() + int(repairAmount))
  2139  	if repairAmount >= 2 {
  2140  		// Mending removes 1 experience point for every 2 durability points. If the repaired durability is less than 2,
  2141  		// then no experience is removed.
  2142  		xp -= int(math.Ceil(repairAmount / 2))
  2143  	}
  2144  	if offHand.Equal(foundItem) {
  2145  		p.SetHeldItems(held, repairedItem)
  2146  	} else if held.Equal(foundItem) {
  2147  		p.SetHeldItems(repairedItem, offHand)
  2148  	} else if slot, ok := p.Armour().Inventory().First(foundItem); ok {
  2149  		_ = p.Armour().Inventory().SetItem(slot, repairedItem)
  2150  	}
  2151  	return xp
  2152  }
  2153  
  2154  // Drop makes the player drop the item.Stack passed as an entity.Item, so that it may be picked up from the
  2155  // ground.
  2156  // The dropped item entity has a pickup delay of 2 seconds.
  2157  // The number of items that was dropped in the end is returned. It is generally the count of the stack passed
  2158  // or 0 if dropping the item.Stack was cancelled.
  2159  func (p *Player) Drop(s item.Stack) int {
  2160  	e := entity.NewItemPickupDelay(s, p.Position().Add(mgl64.Vec3{0, 1.4}), time.Second*2)
  2161  	e.SetVelocity(p.Rotation().Vec3().Mul(0.4))
  2162  
  2163  	ctx := event.C()
  2164  	if p.Handler().HandleItemDrop(ctx, e); ctx.Cancelled() {
  2165  		return 0
  2166  	}
  2167  	p.World().AddEntity(e)
  2168  	return s.Count()
  2169  }
  2170  
  2171  // OpenBlockContainer opens a block container, such as a chest, at the position passed. If no container was
  2172  // present at that location, OpenBlockContainer does nothing.
  2173  // OpenBlockContainer will also do nothing if the player has no session connected to it.
  2174  func (p *Player) OpenBlockContainer(pos cube.Pos) {
  2175  	if p.session() != session.Nop {
  2176  		p.session().OpenBlockContainer(pos)
  2177  	}
  2178  }
  2179  
  2180  // HideEntity hides a world.Entity from the Player so that it can under no circumstance see it. Hidden entities can be
  2181  // made visible again through a call to ShowEntity.
  2182  func (p *Player) HideEntity(e world.Entity) {
  2183  	if p.session() != session.Nop && p != e {
  2184  		p.session().StopShowingEntity(e)
  2185  	}
  2186  }
  2187  
  2188  // ShowEntity shows a world.Entity previously hidden from the Player using HideEntity. It does nothing if the entity
  2189  // wasn't currently hidden.
  2190  func (p *Player) ShowEntity(e world.Entity) {
  2191  	if p.session() != session.Nop {
  2192  		p.session().StartShowingEntity(e)
  2193  	}
  2194  }
  2195  
  2196  // Latency returns a rolling average of latency between the sending and the receiving end of the connection of
  2197  // the player.
  2198  // The latency returned is updated continuously and is half the round trip time (RTT).
  2199  // If the Player does not have a session associated with it, Latency returns 0.
  2200  func (p *Player) Latency() time.Duration {
  2201  	if p.session() == session.Nop {
  2202  		return 0
  2203  	}
  2204  	return p.session().Latency()
  2205  }
  2206  
  2207  // Tick ticks the entity, performing actions such as checking if the player is still breaking a block.
  2208  func (p *Player) Tick(w *world.World, current int64) {
  2209  	if p.Dead() {
  2210  		return
  2211  	}
  2212  	if p.lastTickedWorld != w {
  2213  		p.Handler().HandleChangeWorld(p.lastTickedWorld, w)
  2214  	}
  2215  	p.lastTickedWorld = w
  2216  	if _, ok := w.Liquid(cube.PosFromVec3(p.Position())); !ok {
  2217  		p.StopSwimming()
  2218  		if _, ok := p.Armour().Helmet().Item().(item.TurtleShell); ok {
  2219  			p.AddEffect(effect.New(effect.WaterBreathing{}, 1, time.Second*10).WithoutParticles())
  2220  		}
  2221  	}
  2222  
  2223  	if _, ok := p.Armour().Chestplate().Item().(item.Elytra); ok && p.Gliding() {
  2224  		if t := p.glideTicks.Inc(); t%20 == 0 {
  2225  			d := p.damageItem(p.Armour().Chestplate(), 1)
  2226  			p.armour.SetChestplate(d)
  2227  			if d.Durability() < 2 {
  2228  				p.StopGliding()
  2229  			}
  2230  		}
  2231  	}
  2232  
  2233  	p.checkBlockCollisions(p.vel.Load(), w)
  2234  	p.onGround.Store(p.checkOnGround(w))
  2235  
  2236  	p.effects.Tick(p)
  2237  
  2238  	p.tickFood(w)
  2239  	p.tickAirSupply(w)
  2240  	if p.immunityTicks.Load() > 0 {
  2241  		p.immunityTicks.Dec()
  2242  	}
  2243  	if p.Position()[1] < float64(w.Range()[0]) && p.GameMode().AllowsTakingDamage() && current%10 == 0 {
  2244  		p.Hurt(4, entity.VoidDamageSource{})
  2245  	}
  2246  	if !p.AttackImmune() && p.insideOfSolid(w) {
  2247  		p.Hurt(1, entity.SuffocationDamageSource{})
  2248  	}
  2249  
  2250  	if p.OnFireDuration() > 0 {
  2251  		p.fireTicks.Sub(1)
  2252  		if !p.GameMode().AllowsTakingDamage() || p.OnFireDuration() <= 0 || w.RainingAt(cube.PosFromVec3(p.Position())) {
  2253  			p.Extinguish()
  2254  		}
  2255  		if p.OnFireDuration()%time.Second == 0 && !p.AttackImmune() {
  2256  			p.Hurt(1, block.FireDamageSource{})
  2257  		}
  2258  	}
  2259  
  2260  	if current%4 == 0 && p.usingItem.Load() {
  2261  		held, _ := p.HeldItems()
  2262  		if _, ok := held.Item().(item.Consumable); ok {
  2263  			// Eating particles seem to happen roughly every 4 ticks.
  2264  			for _, v := range p.viewers() {
  2265  				v.ViewEntityAction(p, entity.EatAction{})
  2266  			}
  2267  		}
  2268  	}
  2269  
  2270  	p.cooldownMu.Lock()
  2271  	for it, ti := range p.cooldowns {
  2272  		if time.Now().After(ti) {
  2273  			delete(p.cooldowns, it)
  2274  		}
  2275  	}
  2276  	p.cooldownMu.Unlock()
  2277  
  2278  	if p.session() == session.Nop && !p.Immobile() {
  2279  		m := p.mc.TickMovement(p, p.Position(), p.Velocity(), cube.Rotation{p.yaw.Load(), p.pitch.Load()})
  2280  		m.Send()
  2281  
  2282  		p.vel.Store(m.Velocity())
  2283  		p.Move(m.Position().Sub(p.Position()), 0, 0)
  2284  	} else {
  2285  		p.vel.Store(mgl64.Vec3{})
  2286  	}
  2287  }
  2288  
  2289  // tickAirSupply tick's the player's air supply, consuming it when underwater, and replenishing it when out of water.
  2290  func (p *Player) tickAirSupply(w *world.World) {
  2291  	if !p.canBreathe(w) {
  2292  		if r, ok := p.Armour().Helmet().Enchantment(enchantment.Respiration{}); ok && rand.Float64() <= (enchantment.Respiration{}).Chance(r.Level()) {
  2293  			// Respiration grants a chance to avoid drowning damage every tick.
  2294  			return
  2295  		}
  2296  
  2297  		if ticks := p.airSupplyTicks.Dec(); ticks <= -20 {
  2298  			p.airSupplyTicks.Store(0)
  2299  			if !p.AttackImmune() {
  2300  				p.Hurt(2, entity.DrowningDamageSource{})
  2301  			}
  2302  		}
  2303  		p.breathing = false
  2304  		p.updateState()
  2305  	} else if max := p.maxAirSupplyTicks.Load(); !p.breathing && p.airSupplyTicks.Load() < max {
  2306  		p.airSupplyTicks.Add(5)
  2307  		if p.airSupplyTicks.Load() >= max {
  2308  			p.breathing = true
  2309  			p.airSupplyTicks.Store(max)
  2310  		}
  2311  		p.updateState()
  2312  	}
  2313  }
  2314  
  2315  // tickFood ticks food related functionality, such as the depletion of the food bar and regeneration if it
  2316  // is full enough.
  2317  func (p *Player) tickFood(w *world.World) {
  2318  	p.hunger.foodTick++
  2319  	if p.hunger.foodTick >= 80 {
  2320  		p.hunger.foodTick = 0
  2321  	}
  2322  
  2323  	if p.hunger.foodTick%10 == 0 && (p.hunger.canQuicklyRegenerate() || w.Difficulty().FoodRegenerates()) {
  2324  		if w.Difficulty().FoodRegenerates() {
  2325  			p.AddFood(1)
  2326  		}
  2327  		if p.hunger.foodTick%20 == 0 {
  2328  			p.regenerate(false)
  2329  		}
  2330  	}
  2331  	if p.hunger.foodTick == 0 {
  2332  		if p.hunger.canRegenerate() {
  2333  			p.regenerate(true)
  2334  		} else if p.hunger.starving() {
  2335  			p.starve(w)
  2336  		}
  2337  	}
  2338  
  2339  	if !p.hunger.canSprint() {
  2340  		p.StopSprinting()
  2341  	}
  2342  }
  2343  
  2344  // regenerate attempts to regenerate half a heart of health, typically caused by a full food bar.
  2345  func (p *Player) regenerate(exhaust bool) {
  2346  	if p.Health() == p.MaxHealth() {
  2347  		return
  2348  	}
  2349  	p.Heal(1, entity.FoodHealingSource{})
  2350  	if exhaust {
  2351  		p.Exhaust(6)
  2352  	}
  2353  }
  2354  
  2355  // starve deals starvation damage to the player if the difficult allows it. In peaceful mode, no damage will
  2356  // ever be dealt. In easy mode, damage will only be dealt if the player has more than 10 health. In normal
  2357  // mode, damage will only be dealt if the player has more than 2 health and in hard mode, damage will always
  2358  // be dealt.
  2359  func (p *Player) starve(w *world.World) {
  2360  	if p.Health() > w.Difficulty().StarvationHealthLimit() {
  2361  		p.Hurt(1, StarvationDamageSource{})
  2362  	}
  2363  }
  2364  
  2365  // AirSupply returns the player's remaining air supply.
  2366  func (p *Player) AirSupply() time.Duration {
  2367  	return time.Duration(p.airSupplyTicks.Load()) * time.Second / 20
  2368  }
  2369  
  2370  // SetAirSupply sets the player's remaining air supply.
  2371  func (p *Player) SetAirSupply(duration time.Duration) {
  2372  	p.airSupplyTicks.Store(duration.Milliseconds() / 50)
  2373  	p.updateState()
  2374  }
  2375  
  2376  // MaxAirSupply returns the player's maximum air supply.
  2377  func (p *Player) MaxAirSupply() time.Duration {
  2378  	return time.Duration(p.maxAirSupplyTicks.Load()) * time.Second / 20
  2379  }
  2380  
  2381  // SetMaxAirSupply sets the player's maximum air supply.
  2382  func (p *Player) SetMaxAirSupply(duration time.Duration) {
  2383  	p.maxAirSupplyTicks.Store(duration.Milliseconds() / 50)
  2384  	p.updateState()
  2385  }
  2386  
  2387  // canBreathe returns true if the player can currently breathe.
  2388  func (p *Player) canBreathe(w *world.World) bool {
  2389  	canTakeDamage := p.GameMode().AllowsTakingDamage()
  2390  	_, waterBreathing := p.effects.Effect(effect.WaterBreathing{})
  2391  	_, conduitPower := p.effects.Effect(effect.ConduitPower{})
  2392  	return !canTakeDamage || waterBreathing || conduitPower || (!p.insideOfWater(w) && !p.insideOfSolid(w))
  2393  }
  2394  
  2395  // breathingDistanceBelowEyes is the lowest distance the player can be in water and still be able to breathe based on
  2396  // the player's eye height.
  2397  const breathingDistanceBelowEyes = 0.11111111
  2398  
  2399  // insideOfWater returns true if the player is currently underwater.
  2400  func (p *Player) insideOfWater(w *world.World) bool {
  2401  	pos := cube.PosFromVec3(entity.EyePosition(p))
  2402  	if l, ok := w.Liquid(pos); ok {
  2403  		if _, ok := l.(block.Water); ok {
  2404  			d := float64(l.SpreadDecay()) + 1
  2405  			if l.LiquidFalling() {
  2406  				d = 1
  2407  			}
  2408  			return p.Position().Y() < (pos.Side(cube.FaceUp).Vec3().Y())-(d/9-breathingDistanceBelowEyes)
  2409  		}
  2410  	}
  2411  	return false
  2412  }
  2413  
  2414  // insideOfSolid returns true if the player is inside a solid block.
  2415  func (p *Player) insideOfSolid(w *world.World) bool {
  2416  	pos := cube.PosFromVec3(entity.EyePosition(p))
  2417  	b, box := w.Block(pos), p.Type().BBox(p).Translate(p.Position())
  2418  
  2419  	_, solid := b.Model().(model.Solid)
  2420  	if !solid {
  2421  		// Not solid.
  2422  		return false
  2423  	}
  2424  	d, diffuses := b.(block.LightDiffuser)
  2425  	if diffuses && d.LightDiffusionLevel() == 0 {
  2426  		// Transparent.
  2427  		return false
  2428  	}
  2429  	for _, blockBox := range b.Model().BBox(pos, w) {
  2430  		if blockBox.Translate(pos.Vec3()).IntersectsWith(box) {
  2431  			return true
  2432  		}
  2433  	}
  2434  	return false
  2435  }
  2436  
  2437  // checkCollisions checks the player's block collisions.
  2438  func (p *Player) checkBlockCollisions(vel mgl64.Vec3, w *world.World) {
  2439  	entityBBox := p.Type().BBox(p).Translate(p.Position())
  2440  	deltaX, deltaY, deltaZ := vel[0], vel[1], vel[2]
  2441  
  2442  	p.checkEntityInsiders(w, entityBBox)
  2443  
  2444  	grown := entityBBox.Extend(vel).Grow(0.25)
  2445  	min, max := grown.Min(), grown.Max()
  2446  	minX, minY, minZ := int(math.Floor(min[0])), int(math.Floor(min[1])), int(math.Floor(min[2]))
  2447  	maxX, maxY, maxZ := int(math.Ceil(max[0])), int(math.Ceil(max[1])), int(math.Ceil(max[2]))
  2448  
  2449  	// A prediction of one BBox per block, plus an additional 2, in case
  2450  	blocks := make([]cube.BBox, 0, (maxX-minX)*(maxY-minY)*(maxZ-minZ)+2)
  2451  	for y := minY; y <= maxY; y++ {
  2452  		for x := minX; x <= maxX; x++ {
  2453  			for z := minZ; z <= maxZ; z++ {
  2454  				pos := cube.Pos{x, y, z}
  2455  				boxes := w.Block(pos).Model().BBox(pos, w)
  2456  				for _, box := range boxes {
  2457  					blocks = append(blocks, box.Translate(pos.Vec3()))
  2458  				}
  2459  			}
  2460  		}
  2461  	}
  2462  
  2463  	// epsilon is the epsilon used for thresholds for change used for change in position and velocity.
  2464  	const epsilon = 0.001
  2465  
  2466  	if !mgl64.FloatEqualThreshold(deltaY, 0, epsilon) {
  2467  		// First we move the entity BBox on the Y axis.
  2468  		for _, blockBBox := range blocks {
  2469  			deltaY = entityBBox.YOffset(blockBBox, deltaY)
  2470  		}
  2471  		entityBBox = entityBBox.Translate(mgl64.Vec3{0, deltaY})
  2472  	}
  2473  	if !mgl64.FloatEqualThreshold(deltaX, 0, epsilon) {
  2474  		// Then on the X axis.
  2475  		for _, blockBBox := range blocks {
  2476  			deltaX = entityBBox.XOffset(blockBBox, deltaX)
  2477  		}
  2478  		entityBBox = entityBBox.Translate(mgl64.Vec3{deltaX})
  2479  	}
  2480  	if !mgl64.FloatEqualThreshold(deltaZ, 0, epsilon) {
  2481  		// And finally on the Z axis.
  2482  		for _, blockBBox := range blocks {
  2483  			deltaZ = entityBBox.ZOffset(blockBBox, deltaZ)
  2484  		}
  2485  	}
  2486  
  2487  	p.collidedHorizontally.Store(!mgl64.FloatEqual(deltaX, vel[0]) || !mgl64.FloatEqual(deltaZ, vel[2]))
  2488  	p.collidedVertically.Store(!mgl64.FloatEqual(deltaY, vel[1]))
  2489  }
  2490  
  2491  // checkEntityInsiders checks if the player is colliding with any EntityInsider blocks.
  2492  func (p *Player) checkEntityInsiders(w *world.World, entityBBox cube.BBox) {
  2493  	box := entityBBox.Grow(-0.0001)
  2494  	min, max := cube.PosFromVec3(box.Min()), cube.PosFromVec3(box.Max())
  2495  
  2496  	for y := min[1]; y <= max[1]; y++ {
  2497  		for x := min[0]; x <= max[0]; x++ {
  2498  			for z := min[2]; z <= max[2]; z++ {
  2499  				blockPos := cube.Pos{x, y, z}
  2500  				b := w.Block(blockPos)
  2501  				if collide, ok := b.(block.EntityInsider); ok {
  2502  					collide.EntityInside(blockPos, w, p)
  2503  					if _, liquid := b.(world.Liquid); liquid {
  2504  						continue
  2505  					}
  2506  				}
  2507  
  2508  				if l, ok := w.Liquid(blockPos); ok {
  2509  					if collide, ok := l.(block.EntityInsider); ok {
  2510  						collide.EntityInside(blockPos, w, p)
  2511  					}
  2512  				}
  2513  			}
  2514  		}
  2515  	}
  2516  }
  2517  
  2518  // checkOnGround checks if the player is currently considered to be on the ground.
  2519  func (p *Player) checkOnGround(w *world.World) bool {
  2520  	box := p.Type().BBox(p).Translate(p.Position())
  2521  
  2522  	b := box.Grow(1)
  2523  
  2524  	min, max := cube.PosFromVec3(b.Min()), cube.PosFromVec3(b.Max())
  2525  	for x := min[0]; x <= max[0]; x++ {
  2526  		for z := min[2]; z <= max[2]; z++ {
  2527  			for y := min[1]; y < max[1]; y++ {
  2528  				pos := cube.Pos{x, y, z}
  2529  				boxList := w.Block(pos).Model().BBox(pos, w)
  2530  				for _, bb := range boxList {
  2531  					if bb.GrowVec3(mgl64.Vec3{0, 0.05}).Translate(pos.Vec3()).IntersectsWith(box) {
  2532  						return true
  2533  					}
  2534  				}
  2535  			}
  2536  		}
  2537  	}
  2538  	return false
  2539  }
  2540  
  2541  // Scale returns the scale modifier of the Player. The default value for a normal scale is 1. A scale of 0
  2542  // will make the Player completely invisible.
  2543  func (p *Player) Scale() float64 {
  2544  	return p.scale.Load()
  2545  }
  2546  
  2547  // SetScale changes the scale modifier of the Player. The default value for a normal scale is 1. A scale of 0
  2548  // will make the Player completely invisible.
  2549  func (p *Player) SetScale(s float64) {
  2550  	p.scale.Store(s)
  2551  	p.updateState()
  2552  }
  2553  
  2554  // OnGround checks if the player is considered to be on the ground.
  2555  func (p *Player) OnGround() bool {
  2556  	if p.session() == session.Nop {
  2557  		return p.mc.OnGround()
  2558  	}
  2559  	return p.onGround.Load()
  2560  }
  2561  
  2562  // EyeHeight returns the eye height of the player: 1.62, or 0.52 if the player is swimming.
  2563  func (p *Player) EyeHeight() float64 {
  2564  	if p.swimming.Load() {
  2565  		return 0.52
  2566  	}
  2567  	return 1.62
  2568  }
  2569  
  2570  // PlaySound plays a world.Sound that only this Player can hear. Unlike World.PlaySound, it is not broadcast
  2571  // to players around it.
  2572  func (p *Player) PlaySound(sound world.Sound) {
  2573  	p.session().PlaySound(sound)
  2574  }
  2575  
  2576  // ShowParticle shows a particle that only this Player can see. Unlike World.AddParticle, it is not broadcast
  2577  // to players around it.
  2578  func (p *Player) ShowParticle(pos mgl64.Vec3, particle world.Particle) {
  2579  	p.session().ViewParticle(pos, particle)
  2580  }
  2581  
  2582  // OpenSign makes the player open the sign at the cube.Pos passed, with the specific side provided. The client will not
  2583  // show the interface if it is not aware of a sign at the position.
  2584  func (p *Player) OpenSign(pos cube.Pos, frontSide bool) {
  2585  	p.session().OpenSign(pos, frontSide)
  2586  }
  2587  
  2588  // EditSign edits the sign at the cube.Pos passed and writes the text passed to a sign at that position. If no sign is
  2589  // present, an error is returned.
  2590  func (p *Player) EditSign(pos cube.Pos, frontText, backText string) error {
  2591  	w := p.World()
  2592  	sign, ok := w.Block(pos).(block.Sign)
  2593  	if !ok {
  2594  		return fmt.Errorf("edit sign: no sign at position %v", pos)
  2595  	}
  2596  
  2597  	if sign.Waxed {
  2598  		return nil
  2599  	} else if frontText == sign.Front.Text && backText == sign.Back.Text {
  2600  		return nil
  2601  	}
  2602  
  2603  	ctx := event.C()
  2604  	if frontText != sign.Front.Text {
  2605  		if p.Handler().HandleSignEdit(ctx, true, sign.Front.Text, frontText); ctx.Cancelled() {
  2606  			return nil
  2607  		}
  2608  		sign.Front.Text = frontText
  2609  		sign.Front.Owner = p.XUID()
  2610  	} else {
  2611  		if p.Handler().HandleSignEdit(ctx, false, sign.Back.Text, backText); ctx.Cancelled() {
  2612  			return nil
  2613  		}
  2614  		sign.Back.Text = backText
  2615  		sign.Back.Owner = p.XUID()
  2616  	}
  2617  	w.SetBlock(pos, sign, nil)
  2618  	return nil
  2619  }
  2620  
  2621  // TurnLecternPage edits the lectern at the cube.Pos passed by turning the page to the page passed. If no lectern is
  2622  // present, an error is returned.
  2623  func (p *Player) TurnLecternPage(pos cube.Pos, page int) error {
  2624  	w := p.World()
  2625  	lectern, ok := w.Block(pos).(block.Lectern)
  2626  	if !ok {
  2627  		return fmt.Errorf("edit lectern: no lectern at position %v", pos)
  2628  	}
  2629  
  2630  	ctx := event.C()
  2631  	if p.Handler().HandleLecternPageTurn(ctx, pos, lectern.Page, &page); ctx.Cancelled() {
  2632  		return nil
  2633  	}
  2634  
  2635  	lectern.Page = page
  2636  	w.SetBlock(pos, lectern, nil)
  2637  	return nil
  2638  }
  2639  
  2640  // updateState updates the state of the player to all viewers of the player.
  2641  func (p *Player) updateState() {
  2642  	for _, v := range p.viewers() {
  2643  		v.ViewEntityState(p)
  2644  	}
  2645  }
  2646  
  2647  // Breathing checks if the player is currently able to breathe. If it's underwater and the player does not
  2648  // have the water breathing or conduit power effect, this returns false.
  2649  // If the player is in creative or spectator mode, Breathing always returns true.
  2650  func (p *Player) Breathing() bool {
  2651  	_, breathing := p.Effect(effect.WaterBreathing{})
  2652  	_, conduitPower := p.Effect(effect.ConduitPower{})
  2653  	_, submerged := p.World().Liquid(cube.PosFromVec3(entity.EyePosition(p)))
  2654  	return !p.GameMode().AllowsTakingDamage() || !submerged || breathing || conduitPower
  2655  }
  2656  
  2657  // SwingArm makes the player swing its arm.
  2658  func (p *Player) SwingArm() {
  2659  	if p.Dead() {
  2660  		return
  2661  	}
  2662  	for _, v := range p.viewers() {
  2663  		v.ViewEntityAction(p, entity.SwingArmAction{})
  2664  	}
  2665  }
  2666  
  2667  // PunchAir makes the player punch the air and plays the sound for attacking with no damage.
  2668  func (p *Player) PunchAir() {
  2669  	if p.Dead() {
  2670  		return
  2671  	}
  2672  	ctx := event.C()
  2673  	if p.Handler().HandlePunchAir(ctx); ctx.Cancelled() {
  2674  		return
  2675  	}
  2676  	p.SwingArm()
  2677  	p.World().PlaySound(p.Position(), sound.Attack{})
  2678  }
  2679  
  2680  // damageItem damages the item stack passed with the damage passed and returns the new stack. If the item
  2681  // broke, a breaking sound is played.
  2682  // If the player is not survival, the original stack is returned.
  2683  func (p *Player) damageItem(s item.Stack, d int) item.Stack {
  2684  	if p.GameMode().CreativeInventory() || d == 0 || s.MaxDurability() == -1 {
  2685  		return s
  2686  	}
  2687  	ctx := event.C()
  2688  	if p.Handler().HandleItemDamage(ctx, s, d); ctx.Cancelled() {
  2689  		return s
  2690  	}
  2691  	if e, ok := s.Enchantment(enchantment.Unbreaking{}); ok {
  2692  		d = (enchantment.Unbreaking{}).Reduce(s.Item(), e.Level(), d)
  2693  	}
  2694  	if s = s.Damage(d); s.Empty() {
  2695  		p.World().PlaySound(p.Position(), sound.ItemBreak{})
  2696  	}
  2697  	return s
  2698  }
  2699  
  2700  // subtractItem subtracts d from the count of the item stack passed and returns it, if the player is in
  2701  // survival or adventure mode.
  2702  func (p *Player) subtractItem(s item.Stack, d int) item.Stack {
  2703  	if !p.GameMode().CreativeInventory() && d != 0 {
  2704  		return s.Grow(-d)
  2705  	}
  2706  	return s
  2707  }
  2708  
  2709  // addNewItem adds the new item of the context passed to the inventory.
  2710  func (p *Player) addNewItem(ctx *item.UseContext) {
  2711  	if (ctx.NewItemSurvivalOnly && p.GameMode().CreativeInventory()) || ctx.NewItem.Empty() {
  2712  		return
  2713  	}
  2714  	held, left := p.HeldItems()
  2715  	if held.Empty() {
  2716  		p.SetHeldItems(ctx.NewItem, left)
  2717  		return
  2718  	}
  2719  	n, err := p.Inventory().AddItem(ctx.NewItem)
  2720  	if err != nil {
  2721  		// Not all items could be added to the inventory, so drop the rest.
  2722  		p.Drop(ctx.NewItem.Grow(ctx.NewItem.Count() - n))
  2723  	}
  2724  	if p.Dead() {
  2725  		p.dropContents()
  2726  	}
  2727  }
  2728  
  2729  // canReach checks if a player can reach a position with its current range. The range depends on if the player
  2730  // is either survival or creative mode.
  2731  func (p *Player) canReach(pos mgl64.Vec3) bool {
  2732  	const (
  2733  		creativeRange = 14.0
  2734  		survivalRange = 8.0
  2735  	)
  2736  	if !p.GameMode().AllowsInteraction() {
  2737  		return false
  2738  	}
  2739  	eyes := entity.EyePosition(p)
  2740  
  2741  	if p.GameMode().CreativeInventory() {
  2742  		return eyes.Sub(pos).Len() <= creativeRange && !p.Dead()
  2743  	}
  2744  	return eyes.Sub(pos).Len() <= survivalRange && !p.Dead()
  2745  }
  2746  
  2747  // Disconnect closes the player and removes it from the world.
  2748  // Disconnect, unlike Close, allows a custom message to be passed to show to the player when it is
  2749  // disconnected. The message is formatted following the rules of fmt.Sprintln without a newline at the end.
  2750  func (p *Player) Disconnect(msg ...any) {
  2751  	p.once.Do(func() {
  2752  		p.close(format(msg))
  2753  	})
  2754  }
  2755  
  2756  // Close closes the player and removes it from the world.
  2757  // Close disconnects the player with a 'Connection closed.' message. Disconnect should be used to disconnect a
  2758  // player with a custom message.
  2759  func (p *Player) Close() error {
  2760  	p.once.Do(func() {
  2761  		p.close("Connection closed.")
  2762  	})
  2763  	return nil
  2764  }
  2765  
  2766  // close closes the player without disconnecting it. It executes code shared by both the closing and the
  2767  // disconnecting of players.
  2768  func (p *Player) close(msg string) {
  2769  	// If the player is being disconnected while they are dead, we respawn the player
  2770  	// so that the player logic works correctly the next time they join.
  2771  	if p.Dead() && p.session() != nil {
  2772  		p.Respawn()
  2773  	}
  2774  	p.h.Swap(NopHandler{}).HandleQuit()
  2775  
  2776  	if s := p.s.Swap(nil); s != nil {
  2777  		s.Disconnect(msg)
  2778  		s.CloseConnection()
  2779  		return
  2780  	}
  2781  	// Only remove the player from the world if it's not attached to a session. If it is attached to a session, the
  2782  	// session will remove the player once ready.
  2783  	p.World().RemoveEntity(p)
  2784  }
  2785  
  2786  // load reads the player data from the provider. It uses the default values if the provider
  2787  // returns false.
  2788  func (p *Player) load(data Data) {
  2789  	p.yaw.Store(data.Yaw)
  2790  	p.pitch.Store(data.Pitch)
  2791  
  2792  	p.health.SetMaxHealth(data.MaxHealth)
  2793  	p.health.AddHealth(data.Health - p.Health())
  2794  	p.session().SendHealth(p.health)
  2795  
  2796  	p.absorptionHealth.Store(data.AbsorptionLevel)
  2797  	p.session().SendAbsorption(p.absorptionHealth.Load())
  2798  
  2799  	p.hunger.SetFood(data.Hunger)
  2800  	p.hunger.foodTick = data.FoodTick
  2801  	p.hunger.exhaustionLevel, p.hunger.saturationLevel = data.ExhaustionLevel, data.SaturationLevel
  2802  	p.sendFood()
  2803  
  2804  	p.airSupplyTicks.Store(data.AirSupply)
  2805  	p.maxAirSupplyTicks.Store(data.MaxAirSupply)
  2806  
  2807  	p.experience.Add(data.Experience)
  2808  	p.session().SendExperience(p.experience)
  2809  
  2810  	p.enchantSeed.Store(data.EnchantmentSeed)
  2811  
  2812  	p.gameMode.Store(data.GameMode)
  2813  	for _, potion := range data.Effects {
  2814  		p.AddEffect(potion)
  2815  	}
  2816  	p.fireTicks.Store(data.FireTicks)
  2817  	p.fallDistance.Store(data.FallDistance)
  2818  
  2819  	p.loadInventory(data.Inventory)
  2820  	for slot, stack := range data.EnderChestInventory {
  2821  		_ = p.enderChest.SetItem(slot, stack)
  2822  	}
  2823  }
  2824  
  2825  // loadInventory loads all the data associated with the player inventory.
  2826  func (p *Player) loadInventory(data InventoryData) {
  2827  	for slot, stack := range data.Items {
  2828  		_ = p.Inventory().SetItem(slot, stack)
  2829  	}
  2830  	_ = p.offHand.SetItem(0, data.OffHand)
  2831  	p.Armour().Set(data.Helmet, data.Chestplate, data.Leggings, data.Boots)
  2832  }
  2833  
  2834  // Data returns the player data that needs to be saved. This is used when the player
  2835  // gets disconnected and the player provider needs to save the data.
  2836  func (p *Player) Data() Data {
  2837  	yaw, pitch := p.Rotation().Elem()
  2838  	offHand, _ := p.offHand.Item(0)
  2839  
  2840  	p.hunger.mu.RLock()
  2841  	defer p.hunger.mu.RUnlock()
  2842  
  2843  	return Data{
  2844  		UUID:            p.UUID(),
  2845  		Username:        p.Name(),
  2846  		Position:        p.Position(),
  2847  		Velocity:        mgl64.Vec3{},
  2848  		Yaw:             yaw,
  2849  		Pitch:           pitch,
  2850  		Health:          p.Health(),
  2851  		MaxHealth:       p.MaxHealth(),
  2852  		Hunger:          p.hunger.foodLevel,
  2853  		Experience:      p.Experience(),
  2854  		EnchantmentSeed: p.EnchantmentSeed(),
  2855  		FoodTick:        p.hunger.foodTick,
  2856  		AirSupply:       p.airSupplyTicks.Load(),
  2857  		MaxAirSupply:    p.maxAirSupplyTicks.Load(),
  2858  		ExhaustionLevel: p.hunger.exhaustionLevel,
  2859  		SaturationLevel: p.hunger.saturationLevel,
  2860  		AbsorptionLevel: p.Absorption(),
  2861  		GameMode:        p.GameMode(),
  2862  		Inventory: InventoryData{
  2863  			Items:        p.Inventory().Slots(),
  2864  			Boots:        p.armour.Boots(),
  2865  			Leggings:     p.armour.Leggings(),
  2866  			Chestplate:   p.armour.Chestplate(),
  2867  			Helmet:       p.armour.Helmet(),
  2868  			OffHand:      offHand,
  2869  			MainHandSlot: p.heldSlot.Load(),
  2870  		},
  2871  		EnderChestInventory: p.enderChest.Slots(),
  2872  		Effects:             p.Effects(),
  2873  		FireTicks:           p.fireTicks.Load(),
  2874  		FallDistance:        p.fallDistance.Load(),
  2875  		World:               p.World(),
  2876  	}
  2877  }
  2878  
  2879  // session returns the network session of the player. If it has one, it is returned. If not, a no-op session
  2880  // is returned.
  2881  func (p *Player) session() *session.Session {
  2882  	if s := p.s.Load(); s != nil {
  2883  		return s
  2884  	}
  2885  	return session.Nop
  2886  }
  2887  
  2888  // useContext returns an item.UseContext initialised for a Player.
  2889  func (p *Player) useContext() *item.UseContext {
  2890  	call := func(ctx *event.Context, slot int, it item.Stack, f func(ctx *event.Context, slot int, it item.Stack)) error {
  2891  		if ctx.Cancelled() {
  2892  			return fmt.Errorf("action was cancelled")
  2893  		}
  2894  		f(ctx, slot, it)
  2895  		if ctx.Cancelled() {
  2896  			return fmt.Errorf("action was cancelled")
  2897  		}
  2898  		return nil
  2899  	}
  2900  	return &item.UseContext{
  2901  		SwapHeldWithArmour: func(i int) {
  2902  			src, dst, srcInv, dstInv := int(p.heldSlot.Load()), i, p.inv, p.armour.Inventory()
  2903  			srcIt, _ := srcInv.Item(src)
  2904  			dstIt, _ := dstInv.Item(dst)
  2905  
  2906  			ctx := event.C()
  2907  			_ = call(ctx, src, srcIt, srcInv.Handler().HandleTake)
  2908  			_ = call(ctx, src, dstIt, srcInv.Handler().HandlePlace)
  2909  			_ = call(ctx, dst, dstIt, dstInv.Handler().HandleTake)
  2910  			if err := call(ctx, dst, srcIt, dstInv.Handler().HandlePlace); err == nil {
  2911  				_ = srcInv.SetItem(src, dstIt)
  2912  				_ = dstInv.SetItem(dst, srcIt)
  2913  				p.PlaySound(sound.EquipItem{Item: srcIt.Item()})
  2914  			}
  2915  		},
  2916  		FirstFunc: func(comparable func(item.Stack) bool) (item.Stack, bool) {
  2917  			inv := p.Inventory()
  2918  			s, ok := inv.FirstFunc(comparable)
  2919  			if !ok {
  2920  				return item.Stack{}, false
  2921  			}
  2922  			it, _ := inv.Item(s)
  2923  			return it, ok
  2924  		},
  2925  	}
  2926  }
  2927  
  2928  // Handler returns the Handler of the player.
  2929  func (p *Player) Handler() Handler {
  2930  	return p.h.Load()
  2931  }
  2932  
  2933  // broadcastItems broadcasts the items held to viewers.
  2934  func (p *Player) broadcastItems(int, item.Stack, item.Stack) {
  2935  	for _, viewer := range p.viewers() {
  2936  		viewer.ViewEntityItems(p)
  2937  	}
  2938  }
  2939  
  2940  // broadcastArmour broadcasts the armour equipped to viewers.
  2941  func (p *Player) broadcastArmour(_ int, before, after item.Stack) {
  2942  	if before.Comparable(after) && before.Empty() == after.Empty() {
  2943  		// Only send armour if the type of the armour changed.
  2944  		return
  2945  	}
  2946  	for _, viewer := range p.viewers() {
  2947  		viewer.ViewEntityArmour(p)
  2948  	}
  2949  }
  2950  
  2951  // viewers returns a list of all viewers of the Player.
  2952  func (p *Player) viewers() []world.Viewer {
  2953  	viewers := p.World().Viewers(p.Position())
  2954  	var s world.Viewer = p.session()
  2955  
  2956  	if sliceutil.Index(viewers, s) == -1 {
  2957  		return append(viewers, s)
  2958  	}
  2959  	return viewers
  2960  }
  2961  
  2962  // resendBlocks resends blocks in a world.World at the cube.Pos passed and the block next to it at the cube.Face passed.
  2963  func (p *Player) resendBlocks(pos cube.Pos, w *world.World, faces ...cube.Face) {
  2964  	if p.session() == session.Nop {
  2965  		return
  2966  	}
  2967  	p.resendBlock(pos, w)
  2968  	for _, f := range faces {
  2969  		p.resendBlock(pos.Side(f), w)
  2970  	}
  2971  }
  2972  
  2973  // resendBlock resends the block at a cube.Pos in the world.World passed.
  2974  func (p *Player) resendBlock(pos cube.Pos, w *world.World) {
  2975  	b := w.Block(pos)
  2976  	p.session().ViewBlockUpdate(pos, b, 0)
  2977  	if _, ok := b.(world.Liquid); !ok {
  2978  		if liq, ok := w.Liquid(pos); ok {
  2979  			p.session().ViewBlockUpdate(pos, liq, 1)
  2980  		}
  2981  	}
  2982  }
  2983  
  2984  // format is a utility function to format a list of values to have spaces between them, but no newline at the
  2985  // end, which is typically used for sending messages, popups and tips.
  2986  func format(a []any) string {
  2987  	return strings.TrimSuffix(strings.TrimSuffix(fmt.Sprintln(a...), "\n"), "\n")
  2988  }