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

     1  package item
     2  
     3  import (
     4  	"encoding/binary"
     5  	"github.com/df-mc/dragonfly/server/block/cube"
     6  	"github.com/df-mc/dragonfly/server/entity/effect"
     7  	"github.com/df-mc/dragonfly/server/internal/lang"
     8  	"github.com/df-mc/dragonfly/server/world"
     9  	"github.com/go-gl/mathgl/mgl64"
    10  	"golang.org/x/text/language"
    11  	"image/color"
    12  	"time"
    13  )
    14  
    15  // MaxCounter represents an item that has a specific max count. By default, each item will be expected to have
    16  // a maximum count of 64. MaxCounter may be implemented to change this behaviour.
    17  type MaxCounter interface {
    18  	// MaxCount returns the maximum number of items that a stack may be composed of. The number returned must
    19  	// be positive.
    20  	MaxCount() int
    21  }
    22  
    23  // UsableOnBlock represents an item that may be used on a block. If an item implements this interface, the
    24  // UseOnBlock method is called whenever the item is used on a block.
    25  type UsableOnBlock interface {
    26  	// UseOnBlock is called when an item is used on a block. The world passed is the world that the item was
    27  	// used in. The user passed is the entity that used the item. Usually this entity is a player.
    28  	// The position of the block that was clicked, along with the clicked face and the position clicked
    29  	// relative to the corner of the block are passed.
    30  	// UseOnBlock returns a bool indicating if the item was used successfully.
    31  	UseOnBlock(pos cube.Pos, face cube.Face, clickPos mgl64.Vec3, w *world.World, user User, ctx *UseContext) bool
    32  }
    33  
    34  // UsableOnEntity represents an item that may be used on an entity. If an item implements this interface, the
    35  // UseOnEntity method is called whenever the item is used on an entity.
    36  type UsableOnEntity interface {
    37  	// UseOnEntity is called when an item is used on an entity. The world passed is the world that the item is
    38  	// used in, and the entity clicked and the user of the item are also passed.
    39  	// UseOnEntity returns a bool indicating if the item was used successfully.
    40  	UseOnEntity(e world.Entity, w *world.World, user User, ctx *UseContext) bool
    41  }
    42  
    43  // Usable represents an item that may be used 'in the air'. If an item implements this interface, the Use
    44  // method is called whenever the item is used while pointing at the air. (For example, when throwing an egg.)
    45  type Usable interface {
    46  	// Use is called when the item is used in the air. The user that used the item and the world that the item
    47  	// was used in are passed to the method.
    48  	// Use returns a bool indicating if the item was used successfully.
    49  	Use(w *world.World, user User, ctx *UseContext) bool
    50  }
    51  
    52  // Throwable represents a custom item that can be thrown such as a projectile. This will only have an effect on
    53  // non-vanilla items.
    54  type Throwable interface {
    55  	// SwingAnimation returns true if the client should cause the player's arm to swing when the item is thrown.
    56  	SwingAnimation() bool
    57  }
    58  
    59  // OffHand represents an item that can be held in the off hand.
    60  type OffHand interface {
    61  	// OffHand returns true if the item can be held in the off hand.
    62  	OffHand() bool
    63  }
    64  
    65  // Consumable represents an item that may be consumed by a player. If an item implements this interface, a player
    66  // may use and hold the item to consume it.
    67  type Consumable interface {
    68  	// AlwaysConsumable specifies if the item is always consumable. Normal food can generally only be consumed
    69  	// when the food bar is not full or when in creative mode. Returning true here means the item can always
    70  	// be consumed, like golden apples or potions.
    71  	AlwaysConsumable() bool
    72  	// ConsumeDuration is the duration consuming the item takes. If the player is using the item for at least
    73  	// this duration, the item will be consumed and have its Consume method called.
    74  	ConsumeDuration() time.Duration
    75  	// Consume consumes one item of the Stack that the Consumable is in. The Stack returned is added back to
    76  	// the inventory after consuming the item. For potions, for example, an empty bottle is returned.
    77  	Consume(w *world.World, c Consumer) Stack
    78  }
    79  
    80  // Consumer represents a User that is able to consume Consumable items.
    81  type Consumer interface {
    82  	User
    83  	// Saturate saturates the Consumer's food bar by the amount of food points passed and the saturation by
    84  	// up to as many saturation points as passed. The final saturation will never exceed the final food level.
    85  	Saturate(food int, saturation float64)
    86  	// AddEffect adds an effect.Effect to the Consumer. If the effect is instant, it is applied to the Consumer
    87  	// immediately. If not, the effect is applied to the consumer every time the Tick method is called.
    88  	// AddEffect will overwrite any effects present if the level of the effect is higher than the existing one, or
    89  	// if the effects' levels are equal and the new effect has a longer duration.
    90  	AddEffect(e effect.Effect)
    91  	// RemoveEffect removes any effect that might currently be active on the Consumer.
    92  	RemoveEffect(e effect.Type)
    93  	// Effects returns any effect currently applied to the Consumer. The returned effects are guaranteed not to have
    94  	// expired when returned.
    95  	Effects() []effect.Effect
    96  }
    97  
    98  // DefaultConsumeDuration is the default duration that consuming an item takes. Dried kelp takes half this
    99  // time to be consumed.
   100  const DefaultConsumeDuration = (time.Second * 161) / 100
   101  
   102  // Drinkable represents a custom item that can be drunk. It is used to make the client show the correct drinking
   103  // animation when a player is using an item. This will only have an effect on non-vanilla items.
   104  type Drinkable interface {
   105  	// Drinkable returns if the item can be drunk or not.
   106  	Drinkable() bool
   107  }
   108  
   109  // Glinted represents a custom item that can have a permanent enchantment glint, this glint is purely cosmetic and
   110  // will show regardless of whether it is actually enchanted. An example of this is the enchanted golden apple.
   111  type Glinted interface {
   112  	// Glinted returns whether the item has an enchantment glint.
   113  	Glinted() bool
   114  }
   115  
   116  // HandEquipped represents an item that can be 'hand equipped'. This means the item will show up in third person like
   117  // a tool, sword or stick would, giving them a different orientation in the hand and making them slightly bigger.
   118  type HandEquipped interface {
   119  	// HandEquipped returns whether the item is hand equipped.
   120  	HandEquipped() bool
   121  }
   122  
   123  // Weapon is an item that may be used as a weapon. It has an attack damage which may be different to the 2
   124  // damage that attacking with an empty hand deals.
   125  type Weapon interface {
   126  	// AttackDamage returns the custom attack damage to the weapon. The damage returned must not be negative.
   127  	AttackDamage() float64
   128  }
   129  
   130  // Cooldown represents an item that has a cooldown.
   131  type Cooldown interface {
   132  	// Cooldown is the duration of the cooldown.
   133  	Cooldown() time.Duration
   134  }
   135  
   136  // nameable represents a block that may be named. These are often containers such as chests, which have a
   137  // name displayed in their interface.
   138  type nameable interface {
   139  	// WithName returns the block itself, except with a custom name applied to it.
   140  	WithName(a ...any) world.Item
   141  }
   142  
   143  // Releaser represents an entity that can release items, such as bows.
   144  type Releaser interface {
   145  	User
   146  	// GameMode returns the gamemode of the releaser.
   147  	GameMode() world.GameMode
   148  	// PlaySound plays a world.Sound that only this Releaser can hear.
   149  	PlaySound(sound world.Sound)
   150  }
   151  
   152  // Releasable represents an item that can be released.
   153  type Releasable interface {
   154  	// Release is called when an item is released.
   155  	Release(releaser Releaser, duration time.Duration, ctx *UseContext)
   156  	// Requirements returns the required items to release this item.
   157  	Requirements() []Stack
   158  }
   159  
   160  // User represents an entity that is able to use an item in the world, typically entities such as players,
   161  // which interact with the world using an item.
   162  type User interface {
   163  	Carrier
   164  	SetHeldItems(mainHand, offHand Stack)
   165  
   166  	UsingItem() bool
   167  	ReleaseItem()
   168  	UseItem()
   169  }
   170  
   171  // Carrier represents an entity that is able to carry an item.
   172  type Carrier interface {
   173  	world.Entity
   174  	// HeldItems returns the items currently held by the entity. Viewers of the entity will be able to see
   175  	// these items.
   176  	HeldItems() (mainHand, offHand Stack)
   177  }
   178  
   179  // BeaconPayment represents an item that may be used as payment for a beacon to select effects to be broadcast
   180  // to surrounding players.
   181  type BeaconPayment interface {
   182  	PayableForBeacon() bool
   183  }
   184  
   185  // Compostable represents an item that may be used to fill up a composter.
   186  type Compostable interface {
   187  	// CompostChance returns the chance the item will produce a layer of compost in the range of 0-1.
   188  	CompostChance() float64
   189  }
   190  
   191  // nopReleasable represents a releasable item that does nothing.
   192  type nopReleasable struct{}
   193  
   194  func (nopReleasable) Release(Releaser, time.Duration, *UseContext) {}
   195  func (nopReleasable) Requirements() []Stack {
   196  	return []Stack{}
   197  }
   198  
   199  // defaultFood represents a consumable item with a default consumption duration.
   200  type defaultFood struct{}
   201  
   202  // AlwaysConsumable ...
   203  func (defaultFood) AlwaysConsumable() bool {
   204  	return false
   205  }
   206  
   207  // ConsumeDuration ...
   208  func (d defaultFood) ConsumeDuration() time.Duration {
   209  	return DefaultConsumeDuration
   210  }
   211  
   212  // DisplayName returns the display name of the item as shown in game in the language passed. It panics if an unknown
   213  // item is passed in.
   214  func DisplayName(item world.Item, locale language.Tag) string {
   215  	if c, ok := item.(world.CustomItem); ok {
   216  		return c.Name()
   217  	}
   218  	name, ok := lang.DisplayName(item, locale)
   219  	if !ok {
   220  		panic("should never happen")
   221  	}
   222  	return name
   223  }
   224  
   225  // eyePosition returns the position of the eyes of the entity if the entity implements entity.Eyed, or the
   226  // actual position if it doesn't.
   227  func eyePosition(e world.Entity) mgl64.Vec3 {
   228  	pos := e.Position()
   229  	if eyed, ok := e.(interface{ EyeHeight() float64 }); ok {
   230  		pos = pos.Add(mgl64.Vec3{0, eyed.EyeHeight()})
   231  	}
   232  	return pos
   233  }
   234  
   235  // Int32FromRGBA converts a color.RGBA into an int32. These int32s are present in things such as signs and dyed leather armour.
   236  func int32FromRGBA(x color.RGBA) int32 {
   237  	if x.R == 0 && x.G == 0 && x.B == 0 {
   238  		// Default to black colour. The default (0x000000) is a transparent colour. Text with this colour will not show
   239  		// up on the sign.
   240  		return int32(-0x1000000)
   241  	}
   242  	return int32(binary.BigEndian.Uint32([]byte{x.A, x.R, x.G, x.B}))
   243  }
   244  
   245  // rgbaFromInt32 converts an int32 into a color.RGBA. These int32s are present in things such as signs and dyed leather armour.
   246  func rgbaFromInt32(x int32) color.RGBA {
   247  	b := make([]byte, 4)
   248  	binary.BigEndian.PutUint32(b, uint32(x))
   249  
   250  	return color.RGBA{A: b[0], R: b[1], G: b[2], B: b[3]}
   251  }
   252  
   253  // boolByte returns 1 if the bool passed is true, or 0 if it is false.
   254  func boolByte(b bool) uint8 {
   255  	if b {
   256  		return 1
   257  	}
   258  	return 0
   259  }