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,72 @@
|
||||
package iteminternal
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/item/category"
|
||||
"maps"
|
||||
)
|
||||
|
||||
// ComponentBuilder represents a builder that can be used to construct an item components map to be sent to a client.
|
||||
type ComponentBuilder struct {
|
||||
name string
|
||||
identifier string
|
||||
category category.Category
|
||||
|
||||
properties map[string]any
|
||||
components map[string]any
|
||||
}
|
||||
|
||||
// NewComponentBuilder returns a new component builder with the provided item data.
|
||||
func NewComponentBuilder(name, identifier string, category category.Category) *ComponentBuilder {
|
||||
return &ComponentBuilder{
|
||||
name: name,
|
||||
identifier: identifier,
|
||||
category: category,
|
||||
|
||||
properties: make(map[string]any),
|
||||
components: make(map[string]any),
|
||||
}
|
||||
}
|
||||
|
||||
// AddProperty adds the provided property to the builder.
|
||||
func (builder *ComponentBuilder) AddProperty(name string, value any) {
|
||||
builder.properties[name] = value
|
||||
}
|
||||
|
||||
// AddComponent adds the provided component to the builder.
|
||||
func (builder *ComponentBuilder) AddComponent(name string, value any) {
|
||||
builder.components[name] = value
|
||||
}
|
||||
|
||||
// Construct constructs the final item components map and returns it. It also applies the default properties required
|
||||
// for the item to work without modifying the original maps in the builder.
|
||||
func (builder *ComponentBuilder) Construct() map[string]any {
|
||||
properties := maps.Clone(builder.properties)
|
||||
components := maps.Clone(builder.components)
|
||||
builder.applyDefaultProperties(properties)
|
||||
builder.applyDefaultComponents(components, properties)
|
||||
return map[string]any{"components": components}
|
||||
}
|
||||
|
||||
// applyDefaultProperties applies the default properties to the provided map. It is important that this method does
|
||||
// not modify the builder's properties map directly otherwise Empty() will return false in future use of the builder.
|
||||
func (builder *ComponentBuilder) applyDefaultProperties(x map[string]any) {
|
||||
x["minecraft:icon"] = map[string]any{
|
||||
"textures": map[string]any{
|
||||
"default": builder.identifier,
|
||||
},
|
||||
}
|
||||
x["creative_group"] = builder.category.Group()
|
||||
x["creative_category"] = int32(builder.category.Uint8())
|
||||
if _, ok := x["max_stack_size"]; !ok {
|
||||
x["max_stack_size"] = int32(64)
|
||||
}
|
||||
}
|
||||
|
||||
// applyDefaultComponents applies the default components to the provided map. It is important that this method does not
|
||||
// modify the builder's components map directly otherwise Empty() will return false in future use of the builder.
|
||||
func (builder *ComponentBuilder) applyDefaultComponents(x, properties map[string]any) {
|
||||
x["item_properties"] = properties
|
||||
x["minecraft:display_name"] = map[string]any{
|
||||
"value": builder.name,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package iteminternal
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/item"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Components returns all the components of the given custom item. If the item has no components, a nil map and false
|
||||
// are returned.
|
||||
func Components(it world.CustomItem) map[string]any {
|
||||
category := it.Category()
|
||||
identifier, _ := it.EncodeItem()
|
||||
name := strings.Split(identifier, ":")[1]
|
||||
|
||||
builder := NewComponentBuilder(it.Name(), identifier, category)
|
||||
|
||||
if x, ok := it.(item.Armour); ok {
|
||||
builder.AddComponent("minecraft:armor", map[string]any{
|
||||
"protection": int32(x.DefencePoints()),
|
||||
})
|
||||
|
||||
var slot string
|
||||
switch it.(type) {
|
||||
case item.HelmetType:
|
||||
slot = "slot.armor.head"
|
||||
case item.ChestplateType:
|
||||
slot = "slot.armor.chest"
|
||||
case item.LeggingsType:
|
||||
slot = "slot.armor.legs"
|
||||
case item.BootsType:
|
||||
slot = "slot.armor.feet"
|
||||
}
|
||||
builder.AddComponent("minecraft:wearable", map[string]any{
|
||||
"slot": slot,
|
||||
})
|
||||
}
|
||||
if x, ok := it.(item.Consumable); ok {
|
||||
builder.AddProperty("use_duration", int32(x.ConsumeDuration().Seconds()*20))
|
||||
builder.AddComponent("minecraft:food", map[string]any{
|
||||
"can_always_eat": x.AlwaysConsumable(),
|
||||
})
|
||||
|
||||
if y, ok := it.(item.Drinkable); ok && y.Drinkable() {
|
||||
builder.AddProperty("use_animation", int32(2))
|
||||
} else {
|
||||
builder.AddProperty("use_animation", int32(1))
|
||||
}
|
||||
}
|
||||
if x, ok := it.(item.Cooldown); ok {
|
||||
builder.AddComponent("minecraft:cooldown", map[string]any{
|
||||
"category": name,
|
||||
"duration": float32(x.Cooldown().Seconds()),
|
||||
})
|
||||
}
|
||||
if x, ok := it.(item.Durable); ok {
|
||||
builder.AddComponent("minecraft:durability", map[string]any{
|
||||
"max_durability": int32(x.DurabilityInfo().MaxDurability),
|
||||
})
|
||||
}
|
||||
if x, ok := it.(item.MaxCounter); ok {
|
||||
builder.AddProperty("max_stack_size", int32(x.MaxCount()))
|
||||
}
|
||||
if x, ok := it.(item.OffHand); ok {
|
||||
builder.AddProperty("allow_off_hand", x.OffHand())
|
||||
}
|
||||
if x, ok := it.(item.Throwable); ok {
|
||||
// The data in minecraft:projectile is only used by vanilla server-side, but we must send at least an empty map
|
||||
// so the client will play the throwing animation.
|
||||
builder.AddComponent("minecraft:projectile", map[string]any{})
|
||||
builder.AddComponent("minecraft:throwable", map[string]any{
|
||||
"do_swing_animation": x.SwingAnimation(),
|
||||
})
|
||||
}
|
||||
if x, ok := it.(item.Glinted); ok {
|
||||
builder.AddProperty("foil", x.Glinted())
|
||||
}
|
||||
if x, ok := it.(item.HandEquipped); ok {
|
||||
builder.AddProperty("hand_equipped", x.HandEquipped())
|
||||
}
|
||||
return builder.Construct()
|
||||
}
|
||||
Reference in New Issue
Block a user