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,251 @@
|
||||
package block
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/internal/nbtconv"
|
||||
"github.com/df-mc/dragonfly/server/item"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
"github.com/df-mc/dragonfly/server/world/sound"
|
||||
"github.com/go-gl/mathgl/mgl64"
|
||||
"image/color"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Sign is a non-solid block that can display text on the front and back of the block.
|
||||
type Sign struct {
|
||||
transparent
|
||||
empty
|
||||
bass
|
||||
sourceWaterDisplacer
|
||||
|
||||
// Wood is the type of wood of the sign. This field must have one of the values found in the material
|
||||
// package.
|
||||
Wood WoodType
|
||||
// Attach is the attachment of the Sign. It is either of the type WallAttachment or StandingAttachment.
|
||||
Attach Attachment
|
||||
// Waxed specifies if the Sign has been waxed by a player. If set to true, the Sign can no longer be edited by
|
||||
// anyone and must be destroyed if the text needs to be changed.
|
||||
Waxed bool
|
||||
// Front is the text of the front side of the sign. Anyone can edit this unless the sign is Waxed.
|
||||
Front SignText
|
||||
// Back is the text of the back side of the sign. Anyone can edit this unless the sign is Waxed.
|
||||
Back SignText
|
||||
}
|
||||
|
||||
// SignText represents the data for a single side of a sign. The sign can be edited on the front and back side.
|
||||
type SignText struct {
|
||||
// Text is the text displayed on this side of the sign. The text is automatically wrapped if it does not fit on a line.
|
||||
Text string
|
||||
// BaseColour is the base colour of the text on this side of the sign, changed when using a dye on the sign. The default
|
||||
// colour is black.
|
||||
BaseColour color.RGBA
|
||||
// Glowing specifies if the Sign has glowing text on the current side. If set to true, the text will be visible even
|
||||
// in the dark, and it will have an outline to improve visibility.
|
||||
Glowing bool
|
||||
// Owner holds the XUID of the player that most recently edited this side of the sign.
|
||||
Owner string
|
||||
}
|
||||
|
||||
// SideClosed ...
|
||||
func (s Sign) SideClosed(cube.Pos, cube.Pos, *world.Tx) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// MaxCount ...
|
||||
func (s Sign) MaxCount() int {
|
||||
return 16
|
||||
}
|
||||
|
||||
// FlammabilityInfo ...
|
||||
func (s Sign) FlammabilityInfo() FlammabilityInfo {
|
||||
return newFlammabilityInfo(0, 0, true)
|
||||
}
|
||||
|
||||
// FuelInfo ...
|
||||
func (s Sign) FuelInfo() item.FuelInfo {
|
||||
if !s.Wood.Flammable() {
|
||||
return item.FuelInfo{}
|
||||
}
|
||||
return newFuelInfo(time.Second * 10)
|
||||
}
|
||||
|
||||
// EncodeItem ...
|
||||
func (s Sign) EncodeItem() (name string, meta int16) {
|
||||
return "minecraft:" + s.Wood.String() + "_sign", 0
|
||||
}
|
||||
|
||||
// BreakInfo ...
|
||||
func (s Sign) BreakInfo() BreakInfo {
|
||||
return newBreakInfo(1, alwaysHarvestable, axeEffective, oneOf(Sign{Wood: s.Wood}))
|
||||
}
|
||||
|
||||
// Dye dyes the Sign, changing its base colour to that of the colour passed.
|
||||
func (s Sign) Dye(pos cube.Pos, userPos mgl64.Vec3, c item.Colour) (world.Block, bool) {
|
||||
if s.EditingFrontSide(pos, userPos) {
|
||||
if s.Front.BaseColour == c.SignRGBA() {
|
||||
return s, false
|
||||
}
|
||||
s.Front.BaseColour = c.SignRGBA()
|
||||
} else {
|
||||
if s.Back.BaseColour == c.SignRGBA() {
|
||||
return s, false
|
||||
}
|
||||
s.Back.BaseColour = c.SignRGBA()
|
||||
}
|
||||
return s, true
|
||||
}
|
||||
|
||||
// Ink inks the sign either glowing or non-glowing.
|
||||
func (s Sign) Ink(pos cube.Pos, userPos mgl64.Vec3, glowing bool) (world.Block, bool) {
|
||||
if s.EditingFrontSide(pos, userPos) {
|
||||
if s.Front.Glowing == glowing {
|
||||
return s, false
|
||||
}
|
||||
s.Front.Glowing = glowing
|
||||
} else {
|
||||
if s.Back.Glowing == glowing {
|
||||
return s, false
|
||||
}
|
||||
s.Back.Glowing = glowing
|
||||
}
|
||||
return s, true
|
||||
}
|
||||
|
||||
// Wax waxes a sign to prevent it from further editing.
|
||||
func (s Sign) Wax(cube.Pos, mgl64.Vec3) (world.Block, bool) {
|
||||
if s.Waxed {
|
||||
return s, false
|
||||
}
|
||||
s.Waxed = true
|
||||
return s, true
|
||||
}
|
||||
|
||||
// Activate ...
|
||||
func (s Sign) Activate(pos cube.Pos, _ cube.Face, tx *world.Tx, u item.User, _ *item.UseContext) bool {
|
||||
if editor, ok := u.(SignEditor); ok && !s.Waxed {
|
||||
editor.OpenSign(pos, s.EditingFrontSide(pos, u.Position()))
|
||||
} else if s.Waxed {
|
||||
tx.PlaySound(pos.Vec3(), sound.WaxedSignFailedInteraction{})
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// EditingFrontSide returns if the user is editing the front side of the sign based on their position relative to the
|
||||
// position and direction of the sign.
|
||||
func (s Sign) EditingFrontSide(pos cube.Pos, userPos mgl64.Vec3) bool {
|
||||
return userPos.Sub(pos.Vec3Centre()).Dot(s.Attach.Rotation().Vec3()) > 0
|
||||
}
|
||||
|
||||
// SignEditor represents something that can edit a sign, typically players.
|
||||
type SignEditor interface {
|
||||
OpenSign(pos cube.Pos, frontSide bool)
|
||||
}
|
||||
|
||||
// UseOnBlock ...
|
||||
func (s Sign) 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().Opposite())
|
||||
} else {
|
||||
s.Attach = WallAttachment(face.Direction())
|
||||
}
|
||||
place(tx, pos, s, user, ctx)
|
||||
if editor, ok := user.(SignEditor); ok {
|
||||
editor.OpenSign(pos, true)
|
||||
}
|
||||
return placed(ctx)
|
||||
}
|
||||
|
||||
// NeighbourUpdateTick ...
|
||||
func (s Sign) NeighbourUpdateTick(pos, _ cube.Pos, tx *world.Tx) {
|
||||
if s.Attach.hanging {
|
||||
if _, ok := tx.Block(pos.Side(s.Attach.facing.Opposite().Face())).(Air); ok {
|
||||
breakBlock(s, pos, tx)
|
||||
}
|
||||
} else if _, ok := tx.Block(pos.Side(cube.FaceDown)).(Air); ok {
|
||||
breakBlock(s, pos, tx)
|
||||
}
|
||||
}
|
||||
|
||||
// EncodeBlock ...
|
||||
func (s Sign) EncodeBlock() (name string, properties map[string]any) {
|
||||
woodType := s.Wood.String() + "_"
|
||||
switch s.Wood {
|
||||
case OakWood():
|
||||
woodType = ""
|
||||
case DarkOakWood():
|
||||
woodType = "darkoak_"
|
||||
}
|
||||
if s.Attach.hanging {
|
||||
return "minecraft:" + woodType + "wall_sign", map[string]any{"facing_direction": int32(s.Attach.facing + 2)}
|
||||
}
|
||||
return "minecraft:" + woodType + "standing_sign", map[string]any{"ground_sign_direction": int32(s.Attach.o)}
|
||||
}
|
||||
|
||||
// DecodeNBT ...
|
||||
func (s Sign) DecodeNBT(data map[string]any) any {
|
||||
if nbtconv.String(data, "Text") != "" {
|
||||
// The NBT format changed in 1.19.80 to have separate data for each side of the sign. The old format must still
|
||||
// be supported for backwards compatibility.
|
||||
s.Front.Text = nbtconv.String(data, "Text")
|
||||
s.Front.BaseColour = nbtconv.RGBAFromInt32(nbtconv.Int32(data, "SignTextColor"))
|
||||
s.Front.Glowing = nbtconv.Bool(data, "IgnoreLighting") && nbtconv.Bool(data, "TextIgnoreLegacyBugResolved")
|
||||
return s
|
||||
}
|
||||
|
||||
front, ok := data["FrontText"].(map[string]any)
|
||||
if ok {
|
||||
s.Front.BaseColour = nbtconv.RGBAFromInt32(nbtconv.Int32(front, "Color"))
|
||||
s.Front.Glowing = nbtconv.Bool(front, "GlowingText")
|
||||
s.Front.Text = nbtconv.String(front, "Text")
|
||||
s.Front.Owner = nbtconv.String(front, "Owner")
|
||||
}
|
||||
|
||||
back, ok := data["BackText"].(map[string]any)
|
||||
if ok {
|
||||
s.Back.BaseColour = nbtconv.RGBAFromInt32(nbtconv.Int32(back, "Color"))
|
||||
s.Back.Glowing = nbtconv.Bool(back, "GlowingText")
|
||||
s.Back.Text = nbtconv.String(back, "Text")
|
||||
s.Back.Owner = nbtconv.String(back, "Owner")
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// EncodeNBT ...
|
||||
func (s Sign) EncodeNBT() map[string]any {
|
||||
m := map[string]any{
|
||||
"id": "Sign",
|
||||
"IsWaxed": boolByte(s.Waxed),
|
||||
"FrontText": map[string]any{
|
||||
"SignTextColor": nbtconv.Int32FromRGBA(s.Front.BaseColour),
|
||||
"IgnoreLighting": boolByte(s.Front.Glowing),
|
||||
"Text": s.Front.Text,
|
||||
"TextOwner": s.Front.Owner,
|
||||
},
|
||||
"BackText": map[string]any{
|
||||
"SignTextColor": nbtconv.Int32FromRGBA(s.Back.BaseColour),
|
||||
"IgnoreLighting": boolByte(s.Back.Glowing),
|
||||
"Text": s.Back.Text,
|
||||
"TextOwner": s.Back.Owner,
|
||||
},
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
// allSigns ...
|
||||
func allSigns() (signs []world.Block) {
|
||||
for _, w := range WoodTypes() {
|
||||
for _, d := range cube.Directions() {
|
||||
signs = append(signs, Sign{Wood: w, Attach: WallAttachment(d)})
|
||||
}
|
||||
for o := cube.Orientation(0); o <= 15; o++ {
|
||||
signs = append(signs, Sign{Wood: w, Attach: StandingAttachment(o)})
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user