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 }