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 }