Files
mc/server/block/lever.go
T

133 lines
3.5 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/item"
"github.com/df-mc/dragonfly/server/world"
"github.com/df-mc/dragonfly/server/world/sound"
"github.com/go-gl/mathgl/mgl64"
)
// Lever is a non-solid block that can provide switchable redstone power.
type Lever struct {
empty
transparent
flowingWaterDisplacer
// Powered is if the lever is switched on.
Powered bool
// Facing is the face of the block that the lever is attached to.
Facing cube.Face
// Direction is the direction the lever is pointing. This is only used for levers that are attached on up or down
// faces. Currently, only North and West directions are supported due to Bedrock Edition limitations.
Direction cube.Direction
}
// RedstoneSource ...
func (l Lever) RedstoneSource() bool {
return true
}
// WeakPower ...
func (l Lever) WeakPower(cube.Pos, cube.Face, *world.Tx, bool) int {
if l.Powered {
return 15
}
return 0
}
// StrongPower ...
func (l Lever) StrongPower(_ cube.Pos, face cube.Face, _ *world.Tx, _ bool) int {
if l.Powered && l.Facing == face {
return 15
}
return 0
}
// SideClosed ...
func (l Lever) SideClosed(cube.Pos, cube.Pos, *world.Tx) bool {
return false
}
// NeighbourUpdateTick ...
func (l Lever) NeighbourUpdateTick(pos, _ cube.Pos, tx *world.Tx) {
supportPos := pos.Side(l.Facing.Opposite())
if !tx.Block(supportPos).Model().FaceSolid(supportPos, l.Facing, tx) {
breakBlock(l, pos, tx)
}
}
// UseOnBlock ...
func (l Lever) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, tx *world.Tx, user item.User, ctx *item.UseContext) bool {
pos, face, used := firstReplaceable(tx, pos, face, l)
if !used {
return false
}
supportPos := pos.Side(face.Opposite())
if !tx.Block(supportPos).Model().FaceSolid(supportPos, face, tx) {
return false
}
l.Powered = false
l.Facing = face
l.Direction = cube.North
if face.Axis() == cube.Y && user.Rotation().Direction().Face().Axis() == cube.X {
l.Direction = cube.West
}
place(tx, pos, l, user, ctx)
return placed(ctx)
}
// Activate ...
func (l Lever) Activate(pos cube.Pos, _ cube.Face, tx *world.Tx, _ item.User, _ *item.UseContext) bool {
l.Powered = !l.Powered
tx.SetBlock(pos, l, nil)
if l.Powered {
tx.PlaySound(pos.Vec3Centre(), sound.PowerOn{})
} else {
tx.PlaySound(pos.Vec3Centre(), sound.PowerOff{})
}
updateDirectionalRedstone(pos, tx, l.Facing.Opposite())
return true
}
// BreakInfo ...
func (l Lever) BreakInfo() BreakInfo {
return newBreakInfo(0.5, alwaysHarvestable, nothingEffective, oneOf(Lever{})).withBreakHandler(func(pos cube.Pos, tx *world.Tx, _ item.User) {
updateDirectionalRedstone(pos, tx, l.Facing.Opposite())
})
}
// EncodeItem ...
func (l Lever) EncodeItem() (name string, meta int16) {
return "minecraft:lever", 0
}
// EncodeBlock ...
func (l Lever) EncodeBlock() (string, map[string]any) {
direction := l.Facing.String()
if l.Facing == cube.FaceDown || l.Facing == cube.FaceUp {
axis := "east_west"
if l.Direction == cube.North {
axis = "north_south"
}
direction += "_" + axis
}
return "minecraft:lever", map[string]any{"open_bit": l.Powered, "lever_direction": direction}
}
// allLevers ...
func allLevers() (all []world.Block) {
f := func(facing cube.Face, direction cube.Direction) {
all = append(all, Lever{Facing: facing, Direction: direction})
all = append(all, Lever{Facing: facing, Direction: direction, Powered: true})
}
for _, facing := range cube.Faces() {
f(facing, cube.North)
if facing == cube.FaceDown || facing == cube.FaceUp {
f(facing, cube.West)
}
}
return
}