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

     1  package block
     2  
     3  import (
     4  	"github.com/df-mc/atomic"
     5  	"github.com/df-mc/dragonfly/server/block/cube"
     6  	"github.com/df-mc/dragonfly/server/item"
     7  	"github.com/df-mc/dragonfly/server/item/inventory"
     8  	"github.com/df-mc/dragonfly/server/world"
     9  	"github.com/df-mc/dragonfly/server/world/sound"
    10  	"github.com/go-gl/mathgl/mgl64"
    11  )
    12  
    13  // enderChestOwner represents an entity that has an ender chest inventory.
    14  type enderChestOwner interface {
    15  	ContainerOpener
    16  	EnderChestInventory() *inventory.Inventory
    17  }
    18  
    19  // EnderChest is a type of chest whose contents are exclusive to each player, and can be accessed from anywhere.
    20  // The empty value of EnderChest is not valid. It must be created using block.NewEnderChest().
    21  type EnderChest struct {
    22  	chest
    23  	transparent
    24  	bass
    25  	sourceWaterDisplacer
    26  
    27  	// Facing is the direction that the ender chest is facing.
    28  	Facing cube.Direction
    29  
    30  	viewers *atomic.Int64
    31  }
    32  
    33  // NewEnderChest creates a new initialised ender chest.
    34  func NewEnderChest() EnderChest {
    35  	return EnderChest{viewers: atomic.NewInt64(0)}
    36  }
    37  
    38  // BreakInfo ...
    39  func (c EnderChest) BreakInfo() BreakInfo {
    40  	return newBreakInfo(22.5, pickaxeHarvestable, pickaxeEffective, silkTouchDrop(item.NewStack(Obsidian{}, 8), item.NewStack(NewEnderChest(), 1))).withBlastResistance(3000)
    41  }
    42  
    43  // LightEmissionLevel ...
    44  func (c EnderChest) LightEmissionLevel() uint8 {
    45  	return 7
    46  }
    47  
    48  // SideClosed ...
    49  func (EnderChest) SideClosed(cube.Pos, cube.Pos, *world.World) bool {
    50  	return false
    51  }
    52  
    53  // UseOnBlock ...
    54  func (c EnderChest) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, user item.User, ctx *item.UseContext) (used bool) {
    55  	pos, _, used = firstReplaceable(w, pos, face, c)
    56  	if !used {
    57  		return
    58  	}
    59  	//noinspection GoAssignmentToReceiver
    60  	c = NewEnderChest()
    61  	c.Facing = user.Rotation().Direction().Opposite()
    62  
    63  	place(w, pos, c, user, ctx)
    64  	return placed(ctx)
    65  }
    66  
    67  // Activate ...
    68  func (c EnderChest) Activate(pos cube.Pos, _ cube.Face, _ *world.World, u item.User, _ *item.UseContext) bool {
    69  	if opener, ok := u.(enderChestOwner); ok {
    70  		opener.OpenBlockContainer(pos)
    71  		return true
    72  	}
    73  	return false
    74  }
    75  
    76  // AddViewer ...
    77  func (c EnderChest) AddViewer(w *world.World, pos cube.Pos) {
    78  	if c.viewers.Inc() == 1 {
    79  		c.open(w, pos)
    80  	}
    81  }
    82  
    83  // RemoveViewer ...
    84  func (c EnderChest) RemoveViewer(w *world.World, pos cube.Pos) {
    85  	if c.viewers.Load() == 0 {
    86  		return
    87  	}
    88  	if c.viewers.Dec() == 0 {
    89  		c.close(w, pos)
    90  	}
    91  }
    92  
    93  // open opens the ender chest, displaying the animation and playing a sound.
    94  func (c EnderChest) open(w *world.World, pos cube.Pos) {
    95  	for _, v := range w.Viewers(pos.Vec3()) {
    96  		v.ViewBlockAction(pos, OpenAction{})
    97  	}
    98  	w.PlaySound(pos.Vec3Centre(), sound.ChestOpen{})
    99  }
   100  
   101  // close closes the ender chest, displaying the animation and playing a sound.
   102  func (c EnderChest) close(w *world.World, pos cube.Pos) {
   103  	for _, v := range w.Viewers(pos.Vec3()) {
   104  		v.ViewBlockAction(pos, CloseAction{})
   105  	}
   106  	w.PlaySound(pos.Vec3Centre(), sound.ChestClose{})
   107  }
   108  
   109  // EncodeNBT ...
   110  func (c EnderChest) EncodeNBT() map[string]interface{} {
   111  	return map[string]interface{}{"id": "EnderChest"}
   112  }
   113  
   114  // DecodeNBT ...
   115  func (c EnderChest) DecodeNBT(map[string]interface{}) interface{} {
   116  	return NewEnderChest()
   117  }
   118  
   119  // EncodeItem ...
   120  func (EnderChest) EncodeItem() (name string, meta int16) {
   121  	return "minecraft:ender_chest", 0
   122  }
   123  
   124  // EncodeBlock ...
   125  func (c EnderChest) EncodeBlock() (name string, properties map[string]interface{}) {
   126  	return "minecraft:ender_chest", map[string]any{"minecraft:cardinal_direction": c.Facing.String()}
   127  }
   128  
   129  // allEnderChests ...
   130  func allEnderChests() (chests []world.Block) {
   131  	for _, direction := range cube.Directions() {
   132  		chests = append(chests, EnderChest{Facing: direction})
   133  	}
   134  	return
   135  }