Skip to content

Implement Redstone #983

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 45 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
d2ba2d1
init transaction changes
xNatsuri Dec 26, 2024
b7975c6
Merge branch 'df-mc:master' into redstone-overhaul
xNatsuri Jan 4, 2025
a75402a
changes
xNatsuri Jan 4, 2025
a857388
update
xNatsuri Jan 4, 2025
c56aac7
Merge branch 'df-mc:master' into redstone-overhaul
xNatsuri Jan 4, 2025
693b06b
use math.rand v2
xNatsuri Jan 4, 2025
7f1bd8b
Merge branch 'master' of https://github.com/xNatsuri/dragonfly into r…
xNatsuri Jan 7, 2025
1837f7f
improve RedstoneUpdate for certain blocks
xNatsuri Jan 7, 2025
f9dd6d7
implement lit redstone ore
xNatsuri Jan 7, 2025
eeecf90
implement dropper block
xNatsuri Jan 7, 2025
65efd3a
update to rand v2
xNatsuri Jan 7, 2025
71c7f66
add jukebox logic
xNatsuri Jan 7, 2025
d753c60
remove refactored code
xNatsuri Jan 7, 2025
3eaa037
add note block logic
xNatsuri Jan 7, 2025
536b5d8
Don't allow note to play with block on top
xNatsuri Jan 7, 2025
a07805f
implement more redstone components
xNatsuri Jan 7, 2025
6343a42
Merge branch 'master' of https://github.com/xNatsuri/dragonfly into r…
xNatsuri Jan 8, 2025
441efce
merge conflicts
xNatsuri Jan 8, 2025
25ab0a4
fix dropper logic
xNatsuri Jan 8, 2025
f8b2109
wip dispensers
xNatsuri Jan 8, 2025
1ae64ca
use new ProjectileHit interface
xNatsuri Jan 8, 2025
22c5e3c
Merge branch 'df-mc:master' into redstone-overhaul
xNatsuri Jan 9, 2025
6d6f1ee
implement repeater locking and wip comparators
xNatsuri Jan 9, 2025
a00d24f
Merge remote-tracking branch 'origin/redstone-overhaul' into redstone…
xNatsuri Jan 9, 2025
ab0024b
implement trapped chests
xNatsuri Jan 9, 2025
5e0d84f
trapped chest changes
xNatsuri Jan 9, 2025
2596838
allow repeaters to be placed on pistons
xNatsuri Jan 9, 2025
c572e98
Merge branch 'df-mc:master' into redstone-overhaul
xNatsuri Jan 9, 2025
ee7b2a4
fix bug with torches
xNatsuri Jan 9, 2025
39a3cab
fix bug with trapped chest
xNatsuri Jan 9, 2025
7458132
fix bug with torches
xNatsuri Jan 9, 2025
b8bd8a9
implement slime block
xNatsuri Jan 9, 2025
a7a95b9
add slime block support to pistons
xNatsuri Jan 9, 2025
e11d3b7
make certain blocks PistonImmovable
xNatsuri Jan 9, 2025
a7ced05
make certain blocks PistonBreakable
xNatsuri Jan 9, 2025
1c1fe20
Merge branch 'df-mc:master' into redstone-overhaul
xNatsuri Jan 18, 2025
59d035a
use breakBlock func
xNatsuri Jan 18, 2025
55d7d2c
Merge branch 'df-mc:master' into redstone-overhaul
xNatsuri Jan 25, 2025
d4e7be9
Merge branch 'master' of https://github.com/xNatsuri/dragonfly into r…
xNatsuri Feb 13, 2025
842c507
fix merge conflict
xNatsuri Feb 13, 2025
063a5c6
changes
xNatsuri Feb 13, 2025
3b9e0d3
Merge branch 'df-mc:master' into redstone-overhaul
xNatsuri Feb 17, 2025
2f29eca
fix glowstone being able to receive redstone power
xNatsuri Feb 17, 2025
d2d38c6
Merge branch 'df-mc:master' into redstone-overhaul
xNatsuri Feb 25, 2025
f651230
fix: panic when middle clicking lever
xNatsuri Feb 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cmd/blockhash/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,10 @@ func (b *hashBuilder) ftype(structName, s string, expr ast.Expr, directives map[
return "uint64(" + s + ")", 8
case "Block":
return "world.BlockHash(" + s + ")", 32
case "ButtonType":
return "uint64(" + s + ".Uint8())", 6
case "PressurePlateType":
return "uint64(" + s + ".Uint8())", 8
case "Attachment":
if _, ok := directives["facing_only"]; ok {
log.Println("Found directive: 'facing_only'")
Expand Down
2 changes: 2 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"github.com/df-mc/dragonfly/server"
"github.com/df-mc/dragonfly/server/player/chat"
"github.com/df-mc/dragonfly/server/world"
"github.com/pelletier/go-toml"
"log/slog"
"os"
Expand All @@ -22,6 +23,7 @@ func main() {

srv.Listen()
for p := range srv.Accept() {
p.SetGameMode(world.GameModeCreative)
_ = p
}
}
Expand Down
2 changes: 1 addition & 1 deletion server/block/barrel.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func (b Barrel) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, tx *world
}
//noinspection GoAssignmentToReceiver
b = NewBarrel()
b.Facing = calculateFace(user, pos)
b.Facing = calculateFace(user, pos, false)

place(tx, pos, b, user, ctx)
return placed(ctx)
Expand Down
5 changes: 5 additions & 0 deletions server/block/barrier.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ func (Barrier) SideClosed(cube.Pos, cube.Pos, *world.Tx) bool {
return false
}

// PistonImmovable ...
func (Barrier) PistonImmovable() bool {
return true
}

// EncodeItem ...
func (Barrier) EncodeItem() (name string, meta int16) {
return "minecraft:barrier", 0
Expand Down
5 changes: 5 additions & 0 deletions server/block/beacon.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ func (b Beacon) Level() int {
return b.level
}

// PistonImmovable ...
func (Beacon) PistonImmovable() bool {
return true
}

// Tick recalculates level, recalculates the active state of the beacon, and powers players,
// once every 80 ticks (4 seconds).
func (b Beacon) Tick(currentTick int64, pos cube.Pos, tx *world.Tx) {
Expand Down
5 changes: 5 additions & 0 deletions server/block/bedrock.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,8 @@ func (b Bedrock) EncodeBlock() (name string, properties map[string]any) {
//noinspection SpellCheckingInspection
return "minecraft:bedrock", map[string]any{"infiniburn_bit": b.InfiniteBurning}
}

// PistonImmovable ...
func (Bedrock) PistonImmovable() bool {
return true
}
8 changes: 6 additions & 2 deletions server/block/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ var unknownFace = cube.Face(len(cube.Faces()))
// unknownDirection is a direction that is used for certain block items. This should not be exposed in the API.
var unknownDirection = cube.Direction(len(cube.Directions()))

func calculateFace(user item.User, placePos cube.Pos) cube.Face {
func calculateFace(user item.User, placePos cube.Pos, swapHorizontal bool) cube.Face {
userPos := user.Position()
pos := cube.PosFromVec3(userPos)
if abs(pos[0]-placePos[0]) < 2 && abs(pos[2]-placePos[2]) < 2 {
Expand All @@ -118,7 +118,11 @@ func calculateFace(user item.User, placePos cube.Pos) cube.Face {
return cube.FaceDown
}
}
return user.Rotation().Direction().Opposite().Face()
face := user.Rotation().Direction().Face()
if swapHorizontal {
face = face.Opposite()
}
return face
}

func abs(x int) int {
Expand Down
159 changes: 159 additions & 0 deletions server/block/button.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
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"
"math/rand/v2"
"time"
)

// Button is a non-solid block that can provide temporary redstone power.
type Button struct {
empty
transparent
sourceWaterDisplacer

// Type is the type of the button.
Type ButtonType
// Facing is the face of the block that the button is on.
Facing cube.Face
// Pressed is whether the button is pressed or not.
Pressed bool
}

// FuelInfo ...
func (b Button) FuelInfo() item.FuelInfo {
if b.Type == StoneButton() || b.Type == PolishedBlackstoneButton() {
return item.FuelInfo{}
}
return newFuelInfo(time.Second * 5)
}

// RedstoneSource ...
func (b Button) RedstoneSource() bool {
return true
}

// WeakPower ...
func (b Button) WeakPower(cube.Pos, cube.Face, *world.Tx, bool) int {
if b.Pressed {
return 15
}
return 0
}

// StrongPower ...
func (b Button) StrongPower(_ cube.Pos, face cube.Face, _ *world.Tx, _ bool) int {
if b.Pressed && b.Facing == face {
return 15
}
return 0
}

// ScheduledTick ...
func (b Button) ScheduledTick(pos cube.Pos, tx *world.Tx, r *rand.Rand) {
if !b.Pressed {
return
}
b.Pressed = false
tx.SetBlock(pos, b, nil)
tx.PlaySound(pos.Vec3Centre(), sound.PowerOff{})
updateDirectionalRedstone(pos, tx, b.Facing.Opposite())
}

// NeighbourUpdateTick ...
func (b Button) NeighbourUpdateTick(pos, _ cube.Pos, tx *world.Tx) {
if !tx.Block(pos.Side(b.Facing.Opposite())).Model().FaceSolid(pos.Side(b.Facing.Opposite()), b.Facing, tx) {
breakBlock(b, pos, tx)
updateDirectionalRedstone(pos, tx, b.Facing.Opposite())
}
}

// Activate ...
func (b Button) Activate(pos cube.Pos, _ cube.Face, tx *world.Tx, _ item.User, _ *item.UseContext) bool {
return b.Click(pos, tx)
}

// ProjectileHit ...
func (b Button) ProjectileHit(pos cube.Pos, tx *world.Tx, e world.Entity, face cube.Face) {
if b.Type == StoneButton() || b.Type == PolishedBlackstoneButton() {
return
}

b.Click(pos, tx)
}

// Click ...
func (b Button) Click(pos cube.Pos, tx *world.Tx) bool {
if b.Pressed {
return true
}
b.Pressed = true
tx.SetBlock(pos, b, nil)
tx.PlaySound(pos.Vec3Centre(), sound.PowerOn{})
updateDirectionalRedstone(pos, tx, b.Facing.Opposite())

delay := time.Millisecond * 1500
if b.Type == StoneButton() || b.Type == PolishedBlackstoneButton() {
delay = time.Millisecond * 1000
}
tx.ScheduleBlockUpdate(pos, b, delay)
return true
}

// UseOnBlock ...
func (b Button) 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, b)
if !used {
return false
}
if !tx.Block(pos.Side(face.Opposite())).Model().FaceSolid(pos.Side(face.Opposite()), face, tx) {
return false
}

b.Facing = face
place(tx, pos, b, user, ctx)
return placed(ctx)
}

// BreakInfo ...
func (b Button) BreakInfo() BreakInfo {
harvestTool := alwaysHarvestable
effectiveTool := axeEffective
if b.Type == StoneButton() || b.Type == PolishedBlackstoneButton() {
harvestTool = pickaxeHarvestable
effectiveTool = pickaxeEffective
}
return newBreakInfo(0.5, harvestTool, effectiveTool, oneOf(b)).withBreakHandler(func(pos cube.Pos, tx *world.Tx, _ item.User) {
updateDirectionalRedstone(pos, tx, b.Facing.Opposite())
})
}

// SideClosed ...
func (b Button) SideClosed(cube.Pos, cube.Pos, *world.World) bool {
return false
}

// EncodeItem ...
func (b Button) EncodeItem() (name string, meta int16) {
return "minecraft:" + b.Type.String() + "_button", 0
}

// EncodeBlock ...
func (b Button) EncodeBlock() (string, map[string]any) {
return "minecraft:" + b.Type.String() + "_button", map[string]any{"facing_direction": int32(b.Facing), "button_pressed_bit": b.Pressed}
}

// allButtons ...
func allButtons() (buttons []world.Block) {
for _, w := range ButtonTypes() {
for _, f := range cube.Faces() {
buttons = append(buttons, Button{Type: w, Facing: f})
buttons = append(buttons, Button{Type: w, Facing: f, Pressed: true})
}
}
return
}
69 changes: 69 additions & 0 deletions server/block/button_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package block

// ButtonType represents a type of button.
type ButtonType struct {
button

// Wood is the type of wood of the button.
wood WoodType
}

type button uint8

// WoodButton returns the wood button type.
func WoodButton(w WoodType) ButtonType {
return ButtonType{0, w}
}

// StoneButton returns the stone button type.
func StoneButton() ButtonType {
return ButtonType{button: 1}
}

// PolishedBlackstoneButton returns the polished blackstone button type.
func PolishedBlackstoneButton() ButtonType {
return ButtonType{button: 2}
}

// Uint8 ...
func (b ButtonType) Uint8() uint8 {
return b.wood.Uint8() | uint8(b.button)<<4
}

// Name ...
func (b ButtonType) Name() string {
switch b.button {
case 0:
return b.wood.Name() + " Button"
case 1:
return "Stone Button"
case 2:
return "Polished Blackstone Button"
}
panic("unknown button type")
}

// String ...
func (b ButtonType) String() string {
switch b.button {
case 0:
if b.wood == OakWood() {
return "wooden"
}
return b.wood.String()
case 1:
return "stone"
case 2:
return "polished_blackstone"
}
panic("unknown button type")
}

// ButtonTypes ...
func ButtonTypes() []ButtonType {
types := []ButtonType{StoneButton(), PolishedBlackstoneButton()}
for _, w := range WoodTypes() {
types = append(types, WoodButton(w))
}
return types
}
Loading