up3
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
package creative
|
||||
|
||||
// Category represents a category of items in the creative inventory which are shown as different tabs.
|
||||
type Category struct {
|
||||
category
|
||||
}
|
||||
|
||||
type category uint8
|
||||
|
||||
// ConstructionCategory is the construction category which contains only blocks that do not fall under
|
||||
// any other category.
|
||||
func ConstructionCategory() Category {
|
||||
return Category{1}
|
||||
}
|
||||
|
||||
// NatureCategory is the nature category which contains blocks and items that can be naturally found in the
|
||||
// world.
|
||||
func NatureCategory() Category {
|
||||
return Category{2}
|
||||
}
|
||||
|
||||
// EquipmentCategory is the equipment category which contains tools, armour, food and any other form of
|
||||
// equipment.
|
||||
func EquipmentCategory() Category {
|
||||
return Category{3}
|
||||
}
|
||||
|
||||
// ItemsCategory is the items category for all the miscellaneous items that do not fall under any other
|
||||
// category.
|
||||
func ItemsCategory() Category {
|
||||
return Category{4}
|
||||
}
|
||||
|
||||
// Uint8 returns the category type as a uint8.
|
||||
func (s category) Uint8() uint8 {
|
||||
return uint8(s)
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package creative
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
|
||||
"github.com/df-mc/dragonfly/server/internal/nbtconv"
|
||||
// The following four imports are essential for this package: They make sure this package is loaded after
|
||||
// all these imports. This ensures that all blocks and items are registered before the creative items are
|
||||
// registered in the init function in this package.
|
||||
_ "github.com/df-mc/dragonfly/server/block"
|
||||
"github.com/df-mc/dragonfly/server/item"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
"github.com/sandertv/gophertunnel/minecraft/nbt"
|
||||
)
|
||||
|
||||
// Item represents a registered item in the creative inventory. It holds a stack of the item and a group that
|
||||
// the item is part of.
|
||||
type Item struct {
|
||||
// Stack is the stack of the item that is registered in the creative inventory.
|
||||
Stack item.Stack
|
||||
// Group is the name of the group that the item is part of. If two groups are registered with the same
|
||||
// name, the item will always reside in the first group that was registered.
|
||||
Group string
|
||||
}
|
||||
|
||||
// Group represents a group of items in the creative inventory. Each group has a category, a name and an icon.
|
||||
// If either the name or icon is empty, the group is considered an 'anonymous group' and will not group its
|
||||
// contents together in the creative inventory.
|
||||
type Group struct {
|
||||
// Category is the category of the group. It determines the tab in which the group will be displayed in the
|
||||
// creative inventory.
|
||||
Category Category
|
||||
// Name is the localised name of the group, i.e. "itemGroup.name.planks".
|
||||
Name string
|
||||
// Icon is the item that will be displayed as the icon of the group in the creative inventory.
|
||||
Icon item.Stack
|
||||
}
|
||||
|
||||
// Groups returns a list with all groups that have been registered as a creative group. These groups will be
|
||||
// accessible by players in-game who have creative mode enabled.
|
||||
func Groups() []Group {
|
||||
return creativeGroups
|
||||
}
|
||||
|
||||
// RegisterGroup registers a group as a creative group, exposing it in the creative inventory. It can then
|
||||
// be referenced using its name when calling RegisterItem.
|
||||
func RegisterGroup(group Group) {
|
||||
creativeGroups = append(creativeGroups, group)
|
||||
}
|
||||
|
||||
// Items returns a list with all items that have been registered as a creative item. These items will
|
||||
// be accessible by players in-game who have creative mode enabled.
|
||||
func Items() []Item {
|
||||
return creativeItemStacks
|
||||
}
|
||||
|
||||
// RegisterItem registers an item as a creative item, exposing it in the creative inventory.
|
||||
func RegisterItem(item Item) {
|
||||
creativeItemStacks = append(creativeItemStacks, item)
|
||||
}
|
||||
|
||||
var (
|
||||
//go:embed creative_items.nbt
|
||||
creativeItemData []byte
|
||||
|
||||
// creativeGroups holds a list of all groups that were registered to the creative inventory using
|
||||
// RegisterGroup.
|
||||
creativeGroups []Group
|
||||
// creativeItemStacks holds a list of all item stacks that were registered to the creative inventory using
|
||||
// RegisterItem.
|
||||
creativeItemStacks []Item
|
||||
)
|
||||
|
||||
// creativeGroupEntry holds data of a creative group as present in the creative inventory.
|
||||
type creativeGroupEntry struct {
|
||||
Category int32 `nbt:"category"`
|
||||
Name string `nbt:"name"`
|
||||
Icon creativeItemEntry `nbt:"icon"`
|
||||
}
|
||||
|
||||
// creativeItemEntry holds data of a creative item as present in the creative inventory.
|
||||
type creativeItemEntry struct {
|
||||
Name string `nbt:"name"`
|
||||
Meta int16 `nbt:"meta"`
|
||||
NBT map[string]any `nbt:"nbt,omitempty"`
|
||||
BlockProperties map[string]any `nbt:"block_properties,omitempty"`
|
||||
GroupIndex int32 `nbt:"group_index,omitempty"`
|
||||
}
|
||||
|
||||
// registerCreativeItems initialises the creative items, registering all creative items that have also been registered as
|
||||
// normal items and are present in vanilla.
|
||||
// noinspection GoUnusedFunction
|
||||
//
|
||||
//lint:ignore U1000 Function is used through compiler directives.
|
||||
func registerCreativeItems() {
|
||||
var m struct {
|
||||
Groups []creativeGroupEntry `nbt:"groups"`
|
||||
Items []creativeItemEntry `nbt:"items"`
|
||||
}
|
||||
if err := nbt.Unmarshal(creativeItemData, &m); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for i, group := range m.Groups {
|
||||
name := group.Name
|
||||
if name == "" {
|
||||
name = fmt.Sprint("anon", i)
|
||||
}
|
||||
st, _ := itemStackFromEntry(group.Icon)
|
||||
c := Category{category(group.Category)}
|
||||
RegisterGroup(Group{Category: c, Name: name, Icon: st})
|
||||
}
|
||||
for _, data := range m.Items {
|
||||
if data.GroupIndex >= int32(len(creativeGroups)) {
|
||||
panic(fmt.Errorf("invalid group index %v for item %v", data.GroupIndex, data.Name))
|
||||
}
|
||||
st, ok := itemStackFromEntry(data)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
RegisterItem(Item{st, creativeGroups[data.GroupIndex].Name})
|
||||
}
|
||||
}
|
||||
|
||||
func itemStackFromEntry(data creativeItemEntry) (item.Stack, bool) {
|
||||
var (
|
||||
it world.Item
|
||||
ok bool
|
||||
)
|
||||
if len(data.BlockProperties) > 0 {
|
||||
// Item with a block, try parsing the block, then try asserting that to an item. Blocks no longer
|
||||
// have their metadata sent, but we still need to get that metadata in order to be able to register
|
||||
// different block states as different items.
|
||||
if b, ok := world.BlockByName(data.Name, data.BlockProperties); ok {
|
||||
if it, ok = b.(world.Item); !ok {
|
||||
return item.Stack{}, false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if it, ok = world.ItemByName(data.Name, data.Meta); !ok {
|
||||
// The item wasn't registered, so don't register it as a creative item.
|
||||
return item.Stack{}, false
|
||||
}
|
||||
if _, resultingMeta := it.EncodeItem(); resultingMeta != data.Meta {
|
||||
// We found an item registered with that ID and a meta of 0, but we only need items with strictly
|
||||
// the same meta here.
|
||||
return item.Stack{}, false
|
||||
}
|
||||
}
|
||||
|
||||
if n, ok := it.(world.NBTer); ok {
|
||||
if len(data.NBT) > 0 {
|
||||
it = n.DecodeNBT(data.NBT).(world.Item)
|
||||
}
|
||||
}
|
||||
|
||||
st := item.NewStack(it, 1)
|
||||
if len(data.NBT) > 0 {
|
||||
var invalid bool
|
||||
for _, e := range nbtconv.Slice(data.NBT, "ench") {
|
||||
if v, ok := e.(map[string]any); ok {
|
||||
t, ok := item.EnchantmentByID(int(nbtconv.Int16(v, "id")))
|
||||
if !ok {
|
||||
invalid = true
|
||||
break
|
||||
}
|
||||
st = st.WithEnchantments(item.NewEnchantment(t, int(nbtconv.Int16(v, "lvl"))))
|
||||
}
|
||||
}
|
||||
if invalid {
|
||||
// Invalid enchantment, skip this item.
|
||||
return item.Stack{}, false
|
||||
}
|
||||
}
|
||||
return st, true
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user