Skip to content

implement item.OffHand to offhand items #1062

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions server/item/arrow.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ func (a Arrow) EncodeItem() (name string, meta int16) {
}
return "minecraft:arrow", 0
}

// OffHand ...
func (Arrow) OffHand() bool {
return true
}
5 changes: 5 additions & 0 deletions server/item/firework.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ func (f Firework) RandomisedDuration() time.Duration {
return f.Duration + time.Duration(rand.IntN(int(time.Millisecond*600)))
}

// OffHand ...
func (Firework) OffHand() bool {
return true
}

// EncodeItem ...
func (Firework) EncodeItem() (name string, meta int16) {
return "minecraft:firework_rocket", 0
Expand Down
2 changes: 1 addition & 1 deletion server/item/inventory/armour.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type Armour struct {
// The function passed is called when a slot is changed. It may be nil to not call anything.
func NewArmour(f func(slot int, before, after item.Stack)) *Armour {
inv := New(4, f)
inv.canAdd = canAddArmour
inv.validator = canAddArmour
return &Armour{inv: inv}
}

Expand Down
20 changes: 15 additions & 5 deletions server/item/inventory/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ type Inventory struct {
h Handler
slots []item.Stack

f SlotFunc
canAdd func(s item.Stack, slot int) bool
f SlotFunc
validator SlotValidator
}

// SlotFunc is a function called for each item changed in an Inventory.
type SlotFunc func(slot int, before, after item.Stack)

// SlotValidator is a function that limits changes in the Inventory slot.
type SlotValidator func(s item.Stack, slot int) bool

// ErrSlotOutOfRange is returned by any methods on inventory when a slot is passed which is not within the
// range of valid values for the inventory.
var ErrSlotOutOfRange = errors.New("slot is out of range: must be in range 0 <= slot < inventory.Size()")
Expand All @@ -42,7 +45,7 @@ func New(size int, f SlotFunc) *Inventory {
if f == nil {
f = func(slot int, before, after item.Stack) {}
}
return &Inventory{h: NopHandler{}, slots: make([]item.Stack, size), f: f, canAdd: func(s item.Stack, slot int) bool { return true }}
return &Inventory{h: NopHandler{}, slots: make([]item.Stack, size), f: f, validator: func(s item.Stack, slot int) bool { return true }}
}

// Clone copies an Inventory and returns it, calling the SlotFunc passed for any
Expand All @@ -51,7 +54,7 @@ func (inv *Inventory) Clone(f SlotFunc) *Inventory {
if f == nil {
f = func(slot int, before, after item.Stack) {}
}
return &Inventory{h: NopHandler{}, slots: inv.Slots(), f: f, canAdd: func(s item.Stack, slot int) bool { return true }}
return &Inventory{h: NopHandler{}, slots: inv.Slots(), f: f, validator: func(s item.Stack, slot int) bool { return true }}
}

// SlotFunc changes the function called when a slot in the inventory is changed.
Expand All @@ -61,6 +64,13 @@ func (inv *Inventory) SlotFunc(f SlotFunc) {
inv.f = f
}

// SlotValidator changes the function that limits item placement in the inventory slot.
func (inv *Inventory) SlotValidator(f SlotValidator) {
inv.mu.Lock()
defer inv.mu.Unlock()
inv.validator = f
}

// Item attempts to obtain an item from a specific slot in the inventory. If an item was present in that slot,
// the item is returned and the error is nil. If no item was present in the slot, a Stack with air as its item
// and a count of 0 is returned. Stack.Empty() may be called to check if this is the case.
Expand Down Expand Up @@ -356,7 +366,7 @@ func (inv *Inventory) Handler() Handler {
// setItem sets an item to a specific slot and overwrites the existing item. It calls the function which is
// called for every item change and does so without locking the inventory.
func (inv *Inventory) setItem(slot int, it item.Stack) func() {
if !inv.canAdd(it, slot) {
if !inv.validator(it, slot) {
return func() {}
}
if it.Count() > it.MaxCount() {
Expand Down
5 changes: 5 additions & 0 deletions server/item/nautilus_shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ type NautilusShell struct{}
func (NautilusShell) EncodeItem() (name string, meta int16) {
return "minecraft:nautilus_shell", 0
}

// OffHand ...
func (NautilusShell) OffHand() bool {
return true
}
5 changes: 5 additions & 0 deletions server/item/totem.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@ func (Totem) MaxCount() int {
func (Totem) EncodeItem() (name string, meta int16) {
return "minecraft:totem_of_undying", 0
}

// OffHand ...
func (Totem) OffHand() bool {
return true
}
8 changes: 8 additions & 0 deletions server/player/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ func (t ptype) Open(tx *world.Tx, handle *world.EntityHandle, data *world.Entity
playerData: pd,
}

pd.offHand.SlotValidator(func(s item.Stack, _ int) bool {
if s.Empty() {
return true
}
_, allowedInOffhand := s.Item().(item.OffHand)
return allowedInOffhand
})

if pd.s != nil {
pd.s.HandleInventories(tx, p, pd.inv, pd.offHand, pd.enderChest, pd.ui, pd.armour, pd.heldSlot)
} else {
Expand Down