Files
mc/server/block/skull.go
T

126 lines
3.3 KiB
Go
Raw Permalink Normal View History

2026-07-09 08:33:57 +08:00
package block
import (
"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/block/model"
"github.com/df-mc/dragonfly/server/internal/nbtconv"
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/world"
"github.com/go-gl/mathgl/mgl64"
)
// TODO: Dragon Heads can be powered by redstone
// Skull is a decorative block. There are seven types of skulls: player, zombie, skeleton, wither skeleton, creeper,
// dragon, and piglin.
type Skull struct {
transparent
sourceWaterDisplacer
// Type is the type of the skull.
Type SkullType
// Attach is the attachment of the Skull. It is either of the type WallAttachment or StandingAttachment.
//blockhash:facing_only
Attach Attachment
}
// Helmet ...
func (Skull) Helmet() bool {
return true
}
// DefencePoints ...
func (Skull) DefencePoints() float64 {
return 0
}
// Toughness ...
func (Skull) Toughness() float64 {
return 0
}
// KnockBackResistance ...
func (Skull) KnockBackResistance() float64 {
return 0
}
// Model ...
func (s Skull) Model() world.BlockModel {
return model.Skull{Direction: s.Attach.facing.Face(), Hanging: s.Attach.hanging}
}
// UseOnBlock ...
func (s Skull) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, tx *world.Tx, user item.User, ctx *item.UseContext) (used bool) {
pos, face, used = firstReplaceable(tx, pos, face, s)
if !used || face == cube.FaceDown {
return false
}
if face == cube.FaceUp {
s.Attach = StandingAttachment(user.Rotation().Orientation())
} else {
s.Attach = WallAttachment(face.Direction())
}
place(tx, pos, s, user, ctx)
return placed(ctx)
}
// SideClosed ...
func (Skull) SideClosed(cube.Pos, cube.Pos, *world.Tx) bool {
return false
}
// HasLiquidDrops ...
func (Skull) HasLiquidDrops() bool {
return true
}
// BreakInfo ...
func (s Skull) BreakInfo() BreakInfo {
return newBreakInfo(1, alwaysHarvestable, nothingEffective, oneOf(Skull{Type: s.Type}))
}
// EncodeItem ...
func (s Skull) EncodeItem() (name string, meta int16) {
return "minecraft:" + s.Type.String(), 0
}
// DecodeNBT ...
func (s Skull) DecodeNBT(data map[string]interface{}) interface{} {
if t := skull(nbtconv.Uint8(data, "SkullType")); t != 255 {
// Used to upgrade pre-1.21.40 skulls after their flattening. Any skull placed since will set
// SkullType to 255.
s.Type = SkullType{t}
}
s.Attach.o = cube.OrientationFromYaw(float64(nbtconv.Float32(data, "Rotation")))
return s
}
// EncodeNBT ...
func (s Skull) EncodeNBT() map[string]interface{} {
return map[string]interface{}{"id": "Skull", "SkullType": uint8(255), "Rotation": float32(s.Attach.o.Yaw())}
}
// EncodeBlock ...
func (s Skull) EncodeBlock() (string, map[string]interface{}) {
if s.Attach.hanging {
if s.Attach.facing == unknownDirection {
return "minecraft:" + s.Type.String(), map[string]interface{}{"facing_direction": int32(0)}
}
return "minecraft:" + s.Type.String(), map[string]interface{}{"facing_direction": int32(s.Attach.facing) + 2}
}
return "minecraft:" + s.Type.String(), map[string]interface{}{"facing_direction": int32(1)}
}
// allSkulls ...
func allSkulls() (skulls []world.Block) {
for _, t := range SkullTypes() {
for _, d := range append(cube.Directions(), unknownDirection) {
skulls = append(skulls, Skull{Type: t, Attach: WallAttachment(d)})
}
skulls = append(skulls, Skull{Type: t, Attach: StandingAttachment(0)})
}
return
}