Skip to content

creative items changes #1014

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

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
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
54 changes: 19 additions & 35 deletions server/item/creative/creative.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
_ "embed"
"fmt"
"github.com/df-mc/dragonfly/server/internal/nbtconv"
"slices"

// 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.
Expand All @@ -13,16 +15,6 @@ import (
"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.
Expand All @@ -34,12 +26,25 @@ type Group struct {
Name string
// Icon is the item that will be displayed as the icon of the group in the creative inventory.
Icon item.Stack
// Items are all items that are that belong to this Group.
Items []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
groups := slices.Clone(creativeGroups)
for _, it := range items {
if it.GroupIndex >= int32(len(groups)) {
panic(fmt.Errorf("invalid group index %v for item %v", it.GroupIndex, it.Name))
}
st, ok := itemStackFromEntry(it)
if !ok {
continue
}
groups[it.GroupIndex].Items = append(groups[it.GroupIndex].Items, st)
}
return groups
}

// RegisterGroup registers a group as a creative group, exposing it in the creative inventory. It can then
Expand All @@ -48,27 +53,15 @@ 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)
}
Comment on lines -57 to -60
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why this was removed, as I said on discord:
I dont really know how we should do this, we need a way for people to register their own groups but also inject into vanilla groups


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
// items holds a list of all item stacks that were registered to the creative inventory.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are not item stacks at this point

items []creativeItemEntry
)

// creativeGroupEntry holds data of a creative group as present in the creative inventory.
Expand Down Expand Up @@ -97,6 +90,7 @@ func init() {
if err := nbt.Unmarshal(creativeItemData, &m); err != nil {
panic(err)
}
items = m.Items
for i, group := range m.Groups {
name := group.Name
if name == "" {
Expand All @@ -106,16 +100,6 @@ func init() {
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) {
Expand Down
2 changes: 2 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/df-mc/dragonfly/server/internal/iteminternal"
"github.com/df-mc/dragonfly/server/internal/sliceutil"
_ "github.com/df-mc/dragonfly/server/item" // Imported for maintaining correct initialisation order.
"github.com/df-mc/dragonfly/server/item/creative"
"github.com/df-mc/dragonfly/server/player"
"github.com/df-mc/dragonfly/server/player/chat"
"github.com/df-mc/dragonfly/server/player/skin"
Expand Down Expand Up @@ -539,6 +540,7 @@ func (srv *Server) createPlayer(id uuid.UUID, conn session.Conn, conf player.Con
MaxChunkRadius: srv.conf.MaxChunkRadius,
JoinMessage: srv.conf.JoinMessage,
QuitMessage: srv.conf.QuitMessage,
CreativeGroups: creative.Groups(),
HandleStop: srv.handleSessionClose,
}.New(conn)

Expand Down
22 changes: 18 additions & 4 deletions server/session/handler_crafting.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,15 +159,29 @@ func (h *ItemStackRequestHandler) handleCreativeCraft(a *protocol.CraftCreativeS
if !c.GameMode().CreativeInventory() {
return fmt.Errorf("can only craft creative items in gamemode creative/spectator")
}
index := a.CreativeItemNetworkID - 1
if int(index) >= len(creative.Items()) {
return fmt.Errorf("creative item with network ID %v does not exist", index)
index := int(a.CreativeItemNetworkID - 1)

it, err := itemByIndex(s.conf.CreativeGroups, index)
if err != nil {
return err
}
it := creative.Items()[index].Stack

it = it.Grow(it.MaxCount() - 1)
return h.createResults(s, tx, it)
}

// itemByIndex returns creative item by index.
func itemByIndex(groups []creative.Group, index int) (item.Stack, error) {
Comment on lines +173 to +174
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name and documentation could be better here, document how it works and the case where it returns an error

offset := 0
for _, group := range groups {
if offset+len(group.Items) > index {
return group.Items[index-offset], nil
}
offset += len(group.Items)
}
return item.Stack{}, fmt.Errorf("creative item with network ID %v does not exist", index)
}

// craftingSize gets the crafting size based on the opened container ID.
func (s *Session) craftingSize() uint32 {
if s.openedContainerID.Load() == 1 {
Expand Down
32 changes: 14 additions & 18 deletions server/session/player.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"github.com/sandertv/gophertunnel/minecraft/protocol/packet"
"math"
"net"
"slices"
"time"
_ "unsafe" // Imported for compiler directives.
)
Expand Down Expand Up @@ -834,30 +833,27 @@ func stacksToIngredientItems(inputs []recipe.Item) []protocol.ItemDescriptorCoun
}

// creativeContent returns all creative groups, and creative inventory items as protocol item stacks.
func creativeContent() ([]protocol.CreativeGroup, []protocol.CreativeItem) {
groups := make([]protocol.CreativeGroup, 0, len(creative.Groups()))
for _, group := range creative.Groups() {
func creativeContent(creativeGroups []creative.Group) ([]protocol.CreativeGroup, []protocol.CreativeItem) {
groups := make([]protocol.CreativeGroup, 0, len(creativeGroups))
it := make([]protocol.CreativeItem, 0, len(creativeGroups)*10)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you multiplying by 10?


var itemIdx uint32
for index, group := range creativeGroups {
groups = append(groups, protocol.CreativeGroup{
Category: int32(group.Category.Uint8()),
Name: group.Name,
Icon: deleteDamage(stackFromItem(group.Icon)),
})
}

it := make([]protocol.CreativeItem, 0, len(creative.Items()))
for index, i := range creative.Items() {
group := slices.IndexFunc(creative.Groups(), func(group creative.Group) bool {
return group.Name == i.Group
})
if group < 0 {
continue
for _, stack := range group.Items {
itemIdx++
it = append(it, protocol.CreativeItem{
CreativeItemNetworkID: itemIdx,
Item: deleteDamage(stackFromItem(stack)),
GroupIndex: uint32(index),
})
}
it = append(it, protocol.CreativeItem{
CreativeItemNetworkID: uint32(index) + 1,
Item: deleteDamage(stackFromItem(i.Stack)),
GroupIndex: uint32(group),
})
}

return groups, it
}

Expand Down
5 changes: 4 additions & 1 deletion server/session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/cmd"
"github.com/df-mc/dragonfly/server/item/creative"
"github.com/df-mc/dragonfly/server/item/inventory"
"github.com/df-mc/dragonfly/server/item/recipe"
"github.com/df-mc/dragonfly/server/player/chat"
Expand Down Expand Up @@ -133,6 +134,8 @@ type Config struct {

JoinMessage, QuitMessage chat.Translation

CreativeGroups []creative.Group

HandleStop func(*world.Tx, Controllable)
}

Expand Down Expand Up @@ -173,7 +176,7 @@ func (conf Config) New(conn Conn) *Session {
s.currentLines.Store(&scoreboardLines)

s.registerHandlers()
groups, items := creativeContent()
groups, items := creativeContent(conf.CreativeGroups)
s.writePacket(&packet.CreativeContent{Groups: groups, Items: items})
s.sendRecipes()
s.sendArmourTrimData()
Expand Down