From cc071b66d0ff88c6cae16b655d1077f07547cb4d Mon Sep 17 00:00:00 2001 From: Sandertv Date: Fri, 22 Nov 2024 18:20:31 +0100 Subject: [PATCH] Resolved merge conflicts and replaced SneakingActivatable with Item.UseOnBlock. --- server/block/block.go | 9 -- server/block/brewer.go | 28 +++--- server/block/brewing_stand.go | 24 +++--- server/block/copper.go | 47 +++++----- server/block/copper_door.go | 96 ++++++++++----------- server/block/copper_grate.go | 37 ++++---- server/block/copper_trapdoor.go | 47 +++++----- server/block/log.go | 4 +- server/block/oxidation_type.go | 14 +-- server/block/oxidizable.go | 38 ++------ server/block/slab_type.go | 2 +- server/block/stairs_type.go | 2 +- server/block/wood.go | 4 +- server/item/axe.go | 19 ++-- server/player/player.go | 11 +-- server/player/type.go | 10 ++- server/session/handler_player_auth_input.go | 4 +- 17 files changed, 174 insertions(+), 222 deletions(-) diff --git a/server/block/block.go b/server/block/block.go index b0348a2c2..1c79ddd78 100644 --- a/server/block/block.go +++ b/server/block/block.go @@ -21,15 +21,6 @@ type Activatable interface { Activate(pos cube.Pos, clickedFace cube.Face, tx *world.Tx, u item.User, ctx *item.UseContext) bool } -// SneakingActivatable represents a block that may be activated by a viewer of the world while sneaking. When -// activated, the block will execute some specific logic. -type SneakingActivatable interface { - // SneakingActivate activates the block at a specific block position while sneaking. The face clicked is - // passed, as well as the world in which the block was activated and the viewer that activated it. - // SneakingActivate returns a bool indicating if activating the block was used successfully. - SneakingActivate(pos cube.Pos, clickedFace cube.Face, w *world.World, u item.User, ctx *item.UseContext) bool -} - // Pickable represents a block that may give a different item then the block itself when picked. type Pickable interface { // Pick returns the item that is picked when the block is picked. diff --git a/server/block/brewer.go b/server/block/brewer.go index 90211ed8b..f1540b00f 100644 --- a/server/block/brewer.go +++ b/server/block/brewer.go @@ -37,7 +37,7 @@ func newBrewer() *brewer { } // InsertItem ... -func (b *brewer) InsertItem(h Hopper, pos cube.Pos, w *world.World) bool { +func (b *brewer) InsertItem(h Hopper, pos cube.Pos, tx *world.Tx) bool { for sourceSlot, sourceStack := range h.inventory.Slots() { var slot int @@ -79,7 +79,7 @@ func (b *brewer) InsertItem(h Hopper, pos cube.Pos, w *world.World) bool { } stack := sourceStack.Grow(-sourceStack.Count() + 1) - it, _ := b.Inventory(w, pos).Item(slot) + it, _ := b.Inventory(tx, pos).Item(slot) if !sourceStack.Comparable(it) { // The items are not the same. @@ -93,7 +93,7 @@ func (b *brewer) InsertItem(h Hopper, pos cube.Pos, w *world.World) bool { stack = it.Grow(1) } - _ = b.Inventory(w, pos).SetItem(slot, stack) + _ = b.Inventory(tx, pos).SetItem(slot, stack) _ = h.inventory.SetItem(sourceSlot, sourceStack.Grow(-1)) return true @@ -102,23 +102,17 @@ func (b *brewer) InsertItem(h Hopper, pos cube.Pos, w *world.World) bool { } // ExtractItem ... -func (b *brewer) ExtractItem(h Hopper, pos cube.Pos, w *world.World) bool { +func (b *brewer) ExtractItem(h Hopper, pos cube.Pos, tx *world.Tx) bool { for sourceSlot, sourceStack := range b.inventory.Slots() { - if sourceStack.Empty() { - continue - } - - if sourceSlot == 0 || sourceSlot == 4 { + if sourceStack.Empty() || sourceSlot == 0 || sourceSlot == 4 { continue } - _, err := h.inventory.AddItem(sourceStack.Grow(-sourceStack.Count() + 1)) if err != nil { // The hopper is full. continue } - - _ = b.Inventory(w, pos).SetItem(sourceSlot, sourceStack.Grow(-1)) + _ = b.Inventory(tx, pos).SetItem(sourceSlot, sourceStack.Grow(-1)) return true } return false @@ -139,12 +133,12 @@ func (b *brewer) Fuel() (fuel, maxFuel int32) { } // Inventory returns the inventory of the brewer. -func (b *brewer) Inventory(*world.World, cube.Pos) *inventory.Inventory { +func (b *brewer) Inventory(*world.Tx, cube.Pos) *inventory.Inventory { return b.inventory } // AddViewer adds a viewer to the brewer, so that it is updated whenever the inventory of the brewer is changed. -func (b *brewer) AddViewer(v ContainerViewer, _ *world.World, _ cube.Pos) { +func (b *brewer) AddViewer(v ContainerViewer, _ *world.Tx, _ cube.Pos) { b.mu.Lock() defer b.mu.Unlock() b.viewers[v] = struct{}{} @@ -152,7 +146,7 @@ func (b *brewer) AddViewer(v ContainerViewer, _ *world.World, _ cube.Pos) { // RemoveViewer removes a viewer from the brewer, so that slot updates in the inventory are no longer sent to // it. -func (b *brewer) RemoveViewer(v ContainerViewer, _ *world.World, _ cube.Pos) { +func (b *brewer) RemoveViewer(v ContainerViewer, _ *world.Tx, _ cube.Pos) { b.mu.Lock() defer b.mu.Unlock() delete(b.viewers, v) @@ -174,7 +168,7 @@ func (b *brewer) setFuel(fuel, maxFuel int32) { // tickBrewing ticks the brewer, ensuring the necessary items exist in the brewer, and then processing all inputted // items for the necessary duration. -func (b *brewer) tickBrewing(block string, pos cube.Pos, w *world.World) { +func (b *brewer) tickBrewing(block string, pos cube.Pos, tx *world.Tx) { b.mu.Lock() // Get each item in the brewer. We don't need to validate errors here since we know the bounds of the brewer. @@ -229,7 +223,7 @@ func (b *brewer) tickBrewing(block string, pos cube.Pos, w *world.World) { // Reduce the ingredient by one. defer b.inventory.SetItem(0, ingredient.Grow(-1)) - w.PlaySound(pos.Vec3Centre(), sound.PotionBrewed{}) + tx.PlaySound(pos.Vec3Centre(), sound.PotionBrewed{}) // Decrement the fuel, and reset the duration. b.fuelAmount-- diff --git a/server/block/brewing_stand.go b/server/block/brewing_stand.go index d729e58a6..b217f3b83 100644 --- a/server/block/brewing_stand.go +++ b/server/block/brewing_stand.go @@ -36,12 +36,12 @@ func (b BrewingStand) Model() world.BlockModel { } // SideClosed ... -func (b BrewingStand) SideClosed(cube.Pos, cube.Pos, *world.World) bool { +func (b BrewingStand) SideClosed(cube.Pos, cube.Pos, *world.Tx) bool { return false } // Tick is called to check if the brewing stand should update and start or stop brewing. -func (b BrewingStand) Tick(_ int64, pos cube.Pos, w *world.World) { +func (b BrewingStand) Tick(_ int64, pos cube.Pos, tx *world.Tx) { // Get each item in the brewing stand. We don't need to validate errors here since we know the bounds of the stand. left, _ := b.inventory.Item(1) middle, _ := b.inventory.Item(2) @@ -51,32 +51,32 @@ func (b BrewingStand) Tick(_ int64, pos cube.Pos, w *world.World) { displayLeft, displayMiddle, displayRight := b.LeftSlot, b.MiddleSlot, b.RightSlot b.LeftSlot, b.MiddleSlot, b.RightSlot = !left.Empty(), !middle.Empty(), !right.Empty() if b.LeftSlot != displayLeft || b.MiddleSlot != displayMiddle || b.RightSlot != displayRight { - w.SetBlock(pos, b, nil) + tx.SetBlock(pos, b, nil) } // Tick brewing. - b.tickBrewing("brewing_stand", pos, w) + b.tickBrewing("brewing_stand", pos, tx) } // Activate ... -func (b BrewingStand) Activate(pos cube.Pos, _ cube.Face, _ *world.World, u item.User, _ *item.UseContext) bool { +func (b BrewingStand) Activate(pos cube.Pos, _ cube.Face, tx *world.Tx, u item.User, _ *item.UseContext) bool { if opener, ok := u.(ContainerOpener); ok { - opener.OpenBlockContainer(pos) + opener.OpenBlockContainer(pos, tx) return true } return false } // UseOnBlock ... -func (b BrewingStand) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, user item.User, ctx *item.UseContext) (used bool) { - pos, _, used = firstReplaceable(w, pos, face, b) +func (b BrewingStand) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, tx *world.Tx, user item.User, ctx *item.UseContext) (used bool) { + pos, _, used = firstReplaceable(tx, pos, face, b) if !used { return } //noinspection GoAssignmentToReceiver b = NewBrewingStand() - place(w, pos, b, user, ctx) + place(tx, pos, b, user, ctx) return placed(ctx) } @@ -114,9 +114,9 @@ func (b BrewingStand) DecodeNBT(data map[string]any) any { // BreakInfo ... func (b BrewingStand) BreakInfo() BreakInfo { - return newBreakInfo(0.5, alwaysHarvestable, pickaxeEffective, oneOf(b)).withBreakHandler(func(pos cube.Pos, w *world.World, u item.User) { - for _, i := range b.Inventory(w, pos).Clear() { - dropItem(w, i, pos.Vec3Centre()) + return newBreakInfo(0.5, alwaysHarvestable, pickaxeEffective, oneOf(b)).withBreakHandler(func(pos cube.Pos, tx *world.Tx, u item.User) { + for _, i := range b.Inventory(tx, pos).Clear() { + dropItem(tx, i, pos.Vec3Centre()) } }) } diff --git a/server/block/copper.go b/server/block/copper.go index e9be118f7..04dc0066d 100644 --- a/server/block/copper.go +++ b/server/block/copper.go @@ -4,6 +4,7 @@ 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" ) @@ -21,6 +22,17 @@ type Copper struct { Waxed bool } +func (c Copper) Strip() (world.Block, world.Sound, bool) { + if c.Waxed { + c.Waxed = false + return c, sound.WaxRemoved{}, true + } else if ot, ok := c.Oxidation.Decrease(); ok { + c.Oxidation = ot + return c, sound.CopperScraped{}, true + } + return c, nil, false +} + // BreakInfo ... func (c Copper) BreakInfo() BreakInfo { return newBreakInfo(3, func(t item.Tool) bool { @@ -30,11 +42,9 @@ func (c Copper) BreakInfo() BreakInfo { // Wax waxes the copper block to stop it from oxidising further. func (c Copper) Wax(cube.Pos, mgl64.Vec3) (world.Block, bool) { - if c.Waxed { - return c, false - } + before := c.Waxed c.Waxed = true - return c, true + return c, before != true } func (c Copper) CanOxidate() bool { @@ -45,40 +55,25 @@ func (c Copper) OxidationLevel() OxidationType { return c.Oxidation } -func (c Copper) WithOxidationLevel(o OxidationType) Oxidizable { +func (c Copper) WithOxidationLevel(o OxidationType) Oxidisable { c.Oxidation = o return c } -func (c Copper) Activate(pos cube.Pos, _ cube.Face, w *world.World, user item.User, _ *item.UseContext) bool { - var ok bool - c.Oxidation, c.Waxed, ok = activateOxidizable(pos, w, user, c.Oxidation, c.Waxed) - if ok { - w.SetBlock(pos, c, nil) - return true - } - return false -} - -func (c Copper) SneakingActivate(pos cube.Pos, face cube.Face, w *world.World, user item.User, ctx *item.UseContext) bool { - // Sneaking should still trigger axe functionality. - return c.Activate(pos, face, w, user, ctx) -} - -func (c Copper) RandomTick(pos cube.Pos, w *world.World, r *rand.Rand) { - attemptOxidation(pos, w, r, c) +func (c Copper) RandomTick(pos cube.Pos, tx *world.Tx, r *rand.Rand) { + attemptOxidation(pos, tx, r, c) } // EncodeItem ... func (c Copper) EncodeItem() (name string, meta int16) { - if c.Type == NormalCopper() && c.Oxidation == NormalOxidation() && !c.Waxed { + if c.Type == NormalCopper() && c.Oxidation == UnoxidisedOxidation() && !c.Waxed { return "minecraft:copper_block", 0 } name = "copper" if c.Type != NormalCopper() { name = c.Type.String() + "_" + name } - if c.Oxidation != NormalOxidation() { + if c.Oxidation != UnoxidisedOxidation() { name = c.Oxidation.String() + "_" + name } if c.Waxed { @@ -89,14 +84,14 @@ func (c Copper) EncodeItem() (name string, meta int16) { // EncodeBlock ... func (c Copper) EncodeBlock() (string, map[string]any) { - if c.Type == NormalCopper() && c.Oxidation == NormalOxidation() && !c.Waxed { + if c.Type == NormalCopper() && c.Oxidation == UnoxidisedOxidation() && !c.Waxed { return "minecraft:copper_block", nil } name := "copper" if c.Type != NormalCopper() { name = c.Type.String() + "_" + name } - if c.Oxidation != NormalOxidation() { + if c.Oxidation != UnoxidisedOxidation() { name = c.Oxidation.String() + "_" + name } if c.Waxed { diff --git a/server/block/copper_door.go b/server/block/copper_door.go index 7ca1aabdf..165af4309 100644 --- a/server/block/copper_door.go +++ b/server/block/copper_door.go @@ -31,6 +31,17 @@ type CopperDoor struct { Right bool } +func (d CopperDoor) Strip() (world.Block, world.Sound, bool) { + if d.Waxed { + d.Waxed = false + return d, sound.WaxRemoved{}, true + } else if ot, ok := d.Oxidation.Decrease(); ok { + d.Oxidation = ot + return d, sound.CopperScraped{}, true + } + return d, nil, false +} + // Model ... func (d CopperDoor) Model() world.BlockModel { return model.Door{Facing: d.Facing, Open: d.Open, Right: d.Right} @@ -53,57 +64,57 @@ func (d CopperDoor) OxidationLevel() OxidationType { return d.Oxidation } -func (d CopperDoor) WithOxidationLevel(o OxidationType) Oxidizable { +func (d CopperDoor) WithOxidationLevel(o OxidationType) Oxidisable { d.Oxidation = o return d } // NeighbourUpdateTick ... -func (d CopperDoor) NeighbourUpdateTick(pos, changedNeighbour cube.Pos, w *world.World) { +func (d CopperDoor) NeighbourUpdateTick(pos, changedNeighbour cube.Pos, tx *world.Tx) { if pos == changedNeighbour { return } if d.Top { - if b, ok := w.Block(pos.Side(cube.FaceDown)).(CopperDoor); !ok { - w.SetBlock(pos, nil, nil) - w.AddParticle(pos.Vec3Centre(), particle.BlockBreak{Block: d}) + if b, ok := tx.Block(pos.Side(cube.FaceDown)).(CopperDoor); !ok { + tx.SetBlock(pos, nil, nil) + tx.AddParticle(pos.Vec3Centre(), particle.BlockBreak{Block: d}) } else if d.Oxidation != b.Oxidation || d.Waxed != b.Waxed { d.Oxidation = b.Oxidation d.Waxed = b.Waxed - w.SetBlock(pos, d, nil) + tx.SetBlock(pos, d, nil) } return } - if solid := w.Block(pos.Side(cube.FaceDown)).Model().FaceSolid(pos.Side(cube.FaceDown), cube.FaceUp, w); !solid { - w.SetBlock(pos, nil, nil) - w.AddParticle(pos.Vec3Centre(), particle.BlockBreak{Block: d}) - } else if b, ok := w.Block(pos.Side(cube.FaceUp)).(CopperDoor); !ok { - w.SetBlock(pos, nil, nil) - w.AddParticle(pos.Vec3Centre(), particle.BlockBreak{Block: d}) + if solid := tx.Block(pos.Side(cube.FaceDown)).Model().FaceSolid(pos.Side(cube.FaceDown), cube.FaceUp, tx); !solid { + tx.SetBlock(pos, nil, nil) + tx.AddParticle(pos.Vec3Centre(), particle.BlockBreak{Block: d}) + } else if b, ok := tx.Block(pos.Side(cube.FaceUp)).(CopperDoor); !ok { + tx.SetBlock(pos, nil, nil) + tx.AddParticle(pos.Vec3Centre(), particle.BlockBreak{Block: d}) } else if d.Oxidation != b.Oxidation || d.Waxed != b.Waxed { d.Oxidation = b.Oxidation d.Waxed = b.Waxed - w.SetBlock(pos, d, nil) + tx.SetBlock(pos, d, nil) } } // UseOnBlock handles the directional placing of doors -func (d CopperDoor) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, user item.User, ctx *item.UseContext) bool { +func (d CopperDoor) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, tx *world.Tx, user item.User, ctx *item.UseContext) bool { if face != cube.FaceUp { // Doors can only be placed when clicking the top face. return false } below := pos pos = pos.Side(cube.FaceUp) - if !replaceableWith(w, pos, d) || !replaceableWith(w, pos.Side(cube.FaceUp), d) { + if !replaceableWith(tx, pos, d) || !replaceableWith(tx, pos.Side(cube.FaceUp), d) { return false } - if !w.Block(below).Model().FaceSolid(below, cube.FaceUp, w) { + if !tx.Block(below).Model().FaceSolid(below, cube.FaceUp, tx) { return false } d.Facing = user.Rotation().Direction() - left := w.Block(pos.Side(d.Facing.RotateLeft().Face())) - right := w.Block(pos.Side(d.Facing.RotateRight().Face())) + left := tx.Block(pos.Side(d.Facing.RotateLeft().Face())) + right := tx.Block(pos.Side(d.Facing.RotateRight().Face())) if _, ok := left.(CopperDoor); ok { d.Right = true } @@ -117,42 +128,32 @@ func (d CopperDoor) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *wo } ctx.IgnoreBBox = true - place(w, pos, d, user, ctx) - place(w, pos.Side(cube.FaceUp), CopperDoor{Oxidation: d.Oxidation, Waxed: d.Waxed, Facing: d.Facing, Top: true, Right: d.Right}, user, ctx) + place(tx, pos, d, user, ctx) + place(tx, pos.Side(cube.FaceUp), CopperDoor{Oxidation: d.Oxidation, Waxed: d.Waxed, Facing: d.Facing, Top: true, Right: d.Right}, user, ctx) ctx.SubtractFromCount(1) return placed(ctx) } -func (d CopperDoor) Activate(pos cube.Pos, _ cube.Face, w *world.World, _ item.User, _ *item.UseContext) bool { +func (d CopperDoor) Activate(pos cube.Pos, _ cube.Face, tx *world.Tx, _ item.User, _ *item.UseContext) bool { d.Open = !d.Open - w.SetBlock(pos, d, nil) + tx.SetBlock(pos, d, nil) otherPos := pos.Side(cube.Face(boolByte(!d.Top))) - other := w.Block(otherPos) + other := tx.Block(otherPos) if door, ok := other.(CopperDoor); ok { door.Open = d.Open - w.SetBlock(otherPos, door, nil) + tx.SetBlock(otherPos, door, nil) } if d.Open { - w.PlaySound(pos.Vec3Centre(), sound.DoorOpen{Block: d}) + tx.PlaySound(pos.Vec3Centre(), sound.DoorOpen{Block: d}) return true } - w.PlaySound(pos.Vec3Centre(), sound.DoorClose{Block: d}) + tx.PlaySound(pos.Vec3Centre(), sound.DoorClose{Block: d}) return true } -func (d CopperDoor) SneakingActivate(pos cube.Pos, _ cube.Face, w *world.World, user item.User, _ *item.UseContext) bool { - var ok bool - d.Oxidation, d.Waxed, ok = activateOxidizable(pos, w, user, d.Oxidation, d.Waxed) - if ok { - w.SetBlock(pos, d, nil) - return true - } - return false -} - -func (d CopperDoor) RandomTick(pos cube.Pos, w *world.World, r *rand.Rand) { - attemptOxidation(pos, w, r, d) +func (d CopperDoor) RandomTick(pos cube.Pos, tx *world.Tx, r *rand.Rand) { + attemptOxidation(pos, tx, r, d) } // BreakInfo ... @@ -163,14 +164,14 @@ func (d CopperDoor) BreakInfo() BreakInfo { } // SideClosed ... -func (d CopperDoor) SideClosed(cube.Pos, cube.Pos, *world.World) bool { +func (d CopperDoor) SideClosed(cube.Pos, cube.Pos, *world.Tx) bool { return false } // EncodeItem ... func (d CopperDoor) EncodeItem() (name string, meta int16) { name = "copper_door" - if d.Oxidation != NormalOxidation() { + if d.Oxidation != UnoxidisedOxidation() { name = d.Oxidation.String() + "_" + name } if d.Waxed { @@ -181,18 +182,15 @@ func (d CopperDoor) EncodeItem() (name string, meta int16) { // EncodeBlock ... func (d CopperDoor) EncodeBlock() (name string, properties map[string]any) { - direction := 3 - switch d.Facing { - case cube.South: - direction = 1 - case cube.West: - direction = 2 - case cube.East: - direction = 0 + direction := d.Facing + if d.Facing == cube.East { + d.Facing = cube.North + } else if d.Facing == cube.North { + d.Facing = cube.East } name = "copper_door" - if d.Oxidation != NormalOxidation() { + if d.Oxidation != UnoxidisedOxidation() { name = d.Oxidation.String() + "_" + name } if d.Waxed { diff --git a/server/block/copper_grate.go b/server/block/copper_grate.go index 62dd9581d..38546d5f9 100644 --- a/server/block/copper_grate.go +++ b/server/block/copper_grate.go @@ -4,6 +4,7 @@ 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" ) @@ -37,6 +38,17 @@ func (c CopperGrate) Wax(cube.Pos, mgl64.Vec3) (world.Block, bool) { return c, true } +func (c CopperGrate) Strip() (world.Block, world.Sound, bool) { + if c.Waxed { + c.Waxed = false + return c, sound.WaxRemoved{}, true + } else if ot, ok := c.Oxidation.Decrease(); ok { + c.Oxidation = ot + return c, sound.CopperScraped{}, true + } + return c, nil, false +} + func (c CopperGrate) CanOxidate() bool { return !c.Waxed } @@ -45,34 +57,19 @@ func (c CopperGrate) OxidationLevel() OxidationType { return c.Oxidation } -func (c CopperGrate) WithOxidationLevel(o OxidationType) Oxidizable { +func (c CopperGrate) WithOxidationLevel(o OxidationType) Oxidisable { c.Oxidation = o return c } -func (c CopperGrate) Activate(pos cube.Pos, _ cube.Face, w *world.World, user item.User, _ *item.UseContext) bool { - var ok bool - c.Oxidation, c.Waxed, ok = activateOxidizable(pos, w, user, c.Oxidation, c.Waxed) - if ok { - w.SetBlock(pos, c, nil) - return true - } - return false -} - -func (c CopperGrate) SneakingActivate(pos cube.Pos, face cube.Face, w *world.World, user item.User, ctx *item.UseContext) bool { - // Sneaking should still trigger axe functionality. - return c.Activate(pos, face, w, user, ctx) -} - -func (c CopperGrate) RandomTick(pos cube.Pos, w *world.World, r *rand.Rand) { - attemptOxidation(pos, w, r, c) +func (c CopperGrate) RandomTick(pos cube.Pos, tx *world.Tx, r *rand.Rand) { + attemptOxidation(pos, tx, r, c) } // EncodeItem ... func (c CopperGrate) EncodeItem() (name string, meta int16) { name = "copper_grate" - if c.Oxidation != NormalOxidation() { + if c.Oxidation != UnoxidisedOxidation() { name = c.Oxidation.String() + "_" + name } if c.Waxed { @@ -84,7 +81,7 @@ func (c CopperGrate) EncodeItem() (name string, meta int16) { // EncodeBlock ... func (c CopperGrate) EncodeBlock() (string, map[string]any) { name := "copper_grate" - if c.Oxidation != NormalOxidation() { + if c.Oxidation != UnoxidisedOxidation() { name = c.Oxidation.String() + "_" + name } if c.Waxed { diff --git a/server/block/copper_trapdoor.go b/server/block/copper_trapdoor.go index 91cfc6fd5..6bb85866d 100644 --- a/server/block/copper_trapdoor.go +++ b/server/block/copper_trapdoor.go @@ -36,15 +36,15 @@ func (t CopperTrapdoor) Model() world.BlockModel { // UseOnBlock handles the directional placing of trapdoors and makes sure they are properly placed upside down // when needed. -func (t CopperTrapdoor) UseOnBlock(pos cube.Pos, face cube.Face, clickPos mgl64.Vec3, w *world.World, user item.User, ctx *item.UseContext) bool { - pos, face, used := firstReplaceable(w, pos, face, t) +func (t CopperTrapdoor) UseOnBlock(pos cube.Pos, face cube.Face, clickPos mgl64.Vec3, tx *world.Tx, user item.User, ctx *item.UseContext) bool { + pos, face, used := firstReplaceable(tx, pos, face, t) if !used { return false } t.Facing = user.Rotation().Direction().Opposite() t.Top = (clickPos.Y() > 0.5 && face != cube.FaceUp) || face == cube.FaceDown - place(w, pos, t, user, ctx) + place(tx, pos, t, user, ctx) return placed(ctx) } @@ -57,6 +57,17 @@ func (t CopperTrapdoor) Wax(cube.Pos, mgl64.Vec3) (world.Block, bool) { return t, true } +func (t CopperTrapdoor) Strip() (world.Block, world.Sound, bool) { + if t.Waxed { + t.Waxed = false + return t, sound.WaxRemoved{}, true + } else if ot, ok := t.Oxidation.Decrease(); ok { + t.Oxidation = ot + return t, sound.CopperScraped{}, true + } + return t, nil, false +} + func (t CopperTrapdoor) CanOxidate() bool { return !t.Waxed } @@ -65,34 +76,24 @@ func (t CopperTrapdoor) OxidationLevel() OxidationType { return t.Oxidation } -func (t CopperTrapdoor) WithOxidationLevel(o OxidationType) Oxidizable { +func (t CopperTrapdoor) WithOxidationLevel(o OxidationType) Oxidisable { t.Oxidation = o return t } -func (t CopperTrapdoor) Activate(pos cube.Pos, _ cube.Face, w *world.World, _ item.User, _ *item.UseContext) bool { +func (t CopperTrapdoor) Activate(pos cube.Pos, _ cube.Face, tx *world.Tx, _ item.User, _ *item.UseContext) bool { t.Open = !t.Open - w.SetBlock(pos, t, nil) + tx.SetBlock(pos, t, nil) if t.Open { - w.PlaySound(pos.Vec3Centre(), sound.TrapdoorOpen{Block: t}) + tx.PlaySound(pos.Vec3Centre(), sound.TrapdoorOpen{Block: t}) return true } - w.PlaySound(pos.Vec3Centre(), sound.TrapdoorClose{Block: t}) + tx.PlaySound(pos.Vec3Centre(), sound.TrapdoorClose{Block: t}) return true } -func (t CopperTrapdoor) SneakingActivate(pos cube.Pos, _ cube.Face, w *world.World, user item.User, _ *item.UseContext) bool { - var ok bool - t.Oxidation, t.Waxed, ok = activateOxidizable(pos, w, user, t.Oxidation, t.Waxed) - if ok { - w.SetBlock(pos, t, nil) - return true - } - return false -} - -func (t CopperTrapdoor) RandomTick(pos cube.Pos, w *world.World, r *rand.Rand) { - attemptOxidation(pos, w, r, t) +func (t CopperTrapdoor) RandomTick(pos cube.Pos, tx *world.Tx, r *rand.Rand) { + attemptOxidation(pos, tx, r, t) } // BreakInfo ... @@ -103,14 +104,14 @@ func (t CopperTrapdoor) BreakInfo() BreakInfo { } // SideClosed ... -func (t CopperTrapdoor) SideClosed(cube.Pos, cube.Pos, *world.World) bool { +func (t CopperTrapdoor) SideClosed(cube.Pos, cube.Pos, *world.Tx) bool { return false } // EncodeItem ... func (t CopperTrapdoor) EncodeItem() (name string, meta int16) { name = "copper_trapdoor" - if t.Oxidation != NormalOxidation() { + if t.Oxidation != UnoxidisedOxidation() { name = t.Oxidation.String() + "_" + name } if t.Waxed { @@ -122,7 +123,7 @@ func (t CopperTrapdoor) EncodeItem() (name string, meta int16) { // EncodeBlock ... func (t CopperTrapdoor) EncodeBlock() (name string, properties map[string]any) { name = "copper_trapdoor" - if t.Oxidation != NormalOxidation() { + if t.Oxidation != UnoxidisedOxidation() { name = t.Oxidation.String() + "_" + name } if t.Waxed { diff --git a/server/block/log.go b/server/block/log.go index 8a84b861d..eb58cc602 100644 --- a/server/block/log.go +++ b/server/block/log.go @@ -64,8 +64,8 @@ func (l Log) UseOnBlock(pos cube.Pos, face cube.Face, clickPos mgl64.Vec3, tx *w } // Strip ... -func (l Log) Strip() (world.Block, bool) { - return Log{Axis: l.Axis, Wood: l.Wood, Stripped: true}, !l.Stripped +func (l Log) Strip() (world.Block, world.Sound, bool) { + return Log{Axis: l.Axis, Wood: l.Wood, Stripped: true}, nil, !l.Stripped } // EncodeItem ... diff --git a/server/block/oxidation_type.go b/server/block/oxidation_type.go index 30e34c94e..6f64f92e7 100644 --- a/server/block/oxidation_type.go +++ b/server/block/oxidation_type.go @@ -7,8 +7,8 @@ type OxidationType struct { type oxidation uint8 -// NormalOxidation is the normal variant of oxidation. -func NormalOxidation() OxidationType { +// UnoxidisedOxidation is the normal variant of oxidation. +func UnoxidisedOxidation() OxidationType { return OxidationType{0} } @@ -22,8 +22,8 @@ func WeatheredOxidation() OxidationType { return OxidationType{2} } -// OxidizedOxidation is the oxidized variant of oxidation. -func OxidizedOxidation() OxidationType { +// OxidisedOxidation is the oxidised variant of oxidation. +func OxidisedOxidation() OxidationType { return OxidationType{3} } @@ -53,7 +53,7 @@ func (s oxidation) Decrease() (OxidationType, bool) { if s > 0 { return OxidationType{s - 1}, true } - return NormalOxidation(), false + return UnoxidisedOxidation(), false } // Increase attempts to increase the oxidation level by one. It returns the new oxidation level and if the @@ -62,7 +62,7 @@ func (s oxidation) Increase() (OxidationType, bool) { if s < 3 { return OxidationType{s + 1}, true } - return OxidizedOxidation(), false + return OxidisedOxidation(), false } // String ... @@ -82,5 +82,5 @@ func (s oxidation) String() string { // OxidationTypes ... func OxidationTypes() []OxidationType { - return []OxidationType{NormalOxidation(), ExposedOxidation(), WeatheredOxidation(), OxidizedOxidation()} + return []OxidationType{UnoxidisedOxidation(), ExposedOxidation(), WeatheredOxidation(), OxidisedOxidation()} } diff --git a/server/block/oxidizable.go b/server/block/oxidizable.go index 2a921f6fa..4a4616e14 100644 --- a/server/block/oxidizable.go +++ b/server/block/oxidizable.go @@ -2,48 +2,26 @@ 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" "math/rand" ) -// Oxidizable is a block that can naturally oxidise over time, such as copper. -type Oxidizable interface { +// Oxidisable is a block that can naturally oxidise over time, such as copper. +type Oxidisable interface { world.Block // CanOxidate returns whether the block can oxidate, i.e. if it's not waxed. CanOxidate() bool // OxidationLevel returns the currently level of oxidation of the block. OxidationLevel() OxidationType // WithOxidationLevel returns the oxidizable block with the oxidation level passed. - WithOxidationLevel(OxidationType) Oxidizable -} - -// activateOxidizable performs the logic for activating an oxidizable block, returning the updated oxidation -// level and wax state of the block, as well as whether the block was successfully activated. This function -// will not handle the setting of the block if it has been modified. -func activateOxidizable(pos cube.Pos, w *world.World, user item.User, o OxidationType, waxed bool) (OxidationType, bool, bool) { - mainHand, _ := user.HeldItems() - // TODO: Immediately return false if holding shield in offhand (https://bugs.mojang.com/browse/MC-270047). - if _, ok := mainHand.Item().(item.Axe); !ok { - return o, waxed, false - } else if waxed { - w.PlaySound(pos.Vec3Centre(), sound.WaxRemoved{}) - return o, false, true - } - - if ox, ok := o.Decrease(); ok { - w.PlaySound(pos.Vec3Centre(), sound.CopperScraped{}) - return ox, false, true - } - return o, false, true + WithOxidationLevel(OxidationType) Oxidisable } // attemptOxidation attempts to oxidise the block at the position passed. The details for this logic is // described on the Minecraft Wiki: https://minecraft.wiki/w/Oxidation. -func attemptOxidation(pos cube.Pos, w *world.World, r *rand.Rand, o Oxidizable) { +func attemptOxidation(pos cube.Pos, tx *world.Tx, r *rand.Rand, o Oxidisable) { level := o.OxidationLevel() - if level == OxidizedOxidation() || !o.CanOxidate() { + if level == OxidisedOxidation() || !o.CanOxidate() { return } else if r.Float64() > 64.0/1125.0 { return @@ -62,7 +40,7 @@ func attemptOxidation(pos cube.Pos, w *world.World, r *rand.Rand, o Oxidizable) continue } - b, ok := w.Block(nPos).(Oxidizable) + b, ok := tx.Block(nPos).(Oxidisable) if !ok || !b.CanOxidate() { continue } else if b.OxidationLevel().Uint8() < level.Uint8() { @@ -77,13 +55,13 @@ func attemptOxidation(pos cube.Pos, w *world.World, r *rand.Rand, o Oxidizable) } chance := float64(higher+1) / float64(all+1) - if level == NormalOxidation() { + if level == UnoxidisedOxidation() { chance *= chance * 0.75 } else { chance *= chance } if r.Float64() < chance { level, _ = level.Increase() - w.SetBlock(pos, o.WithOxidationLevel(level), nil) + tx.SetBlock(pos, o.WithOxidationLevel(level), nil) } } diff --git a/server/block/slab_type.go b/server/block/slab_type.go index a1f25fcf0..c3b435e8f 100644 --- a/server/block/slab_type.go +++ b/server/block/slab_type.go @@ -39,7 +39,7 @@ func encodeSlabBlock(block world.Block, double bool) (id string, suffix string) suffix = "double_" + suffix } var name string - if block.Oxidation != NormalOxidation() { + if block.Oxidation != UnoxidisedOxidation() { name = block.Oxidation.String() + "_" } if block.Waxed { diff --git a/server/block/stairs_type.go b/server/block/stairs_type.go index 2dbef33ad..7651205cb 100644 --- a/server/block/stairs_type.go +++ b/server/block/stairs_type.go @@ -29,7 +29,7 @@ func encodeStairsBlock(block world.Block) string { case Copper: if block.Type == CutCopper() { name := "cut_copper" - if block.Oxidation != NormalOxidation() { + if block.Oxidation != UnoxidisedOxidation() { name = block.Oxidation.String() + "_" + name } if block.Waxed { diff --git a/server/block/wood.go b/server/block/wood.go index f423c1529..f6f56bb2d 100644 --- a/server/block/wood.go +++ b/server/block/wood.go @@ -63,8 +63,8 @@ func (w Wood) UseOnBlock(pos cube.Pos, face cube.Face, clickPos mgl64.Vec3, tx * } // Strip ... -func (w Wood) Strip() (world.Block, bool) { - return Wood{Axis: w.Axis, Wood: w.Wood, Stripped: true}, !w.Stripped +func (w Wood) Strip() (world.Block, world.Sound, bool) { + return Wood{Axis: w.Axis, Wood: w.Wood, Stripped: true}, nil, !w.Stripped } // EncodeItem ... diff --git a/server/item/axe.go b/server/item/axe.go index 4744e991f..a3c646ceb 100644 --- a/server/item/axe.go +++ b/server/item/axe.go @@ -17,10 +17,13 @@ type Axe struct { // UseOnBlock handles the stripping of logs when a player clicks a log with an axe. func (a Axe) UseOnBlock(pos cube.Pos, face cube.Face, clickPos mgl64.Vec3, tx *world.Tx, user User, ctx *UseContext) bool { - if s, ok := tx.Block(pos).(strippable); ok { - if res, ok := s.Strip(); ok { + if s, ok := tx.Block(pos).(Strippable); ok { + if res, so, ok := s.Strip(); ok { tx.SetBlock(pos, res, nil) tx.PlaySound(pos.Vec3(), sound.ItemUseOn{Block: res}) + if so != nil { + tx.PlaySound(pos.Vec3(), so) + } ctx.DamageItem(1) return true @@ -29,11 +32,13 @@ func (a Axe) UseOnBlock(pos cube.Pos, face cube.Face, clickPos mgl64.Vec3, tx *w return false } -// strippable represents a block that can be stripped. -type strippable interface { - // Strip returns a block that is the result of stripping it. Alternatively, the bool returned may be false to - // indicate the block couldn't be stripped. - Strip() (world.Block, bool) +// Strippable represents a block that can be stripped by right-clicking it with +// an axe. +type Strippable interface { + // Strip returns a block that is the result of stripping it. Alternatively, + // the bool returned may be false to indicate the block couldn't be + // stripped. + Strip() (world.Block, world.Sound, bool) } // MaxCount always returns 1. diff --git a/server/player/player.go b/server/player/player.go index 99ede53d7..42b134f76 100644 --- a/server/player/player.go +++ b/server/player/player.go @@ -66,7 +66,7 @@ type playerData struct { cooldowns map[string]time.Time - speed float64 + speed float64 flightSpeed float64 health *entity.HealthManager @@ -1473,15 +1473,6 @@ func (p *Player) UseItemOnBlock(pos cube.Pos, face cube.Face, clickPos mgl64.Vec } } } - if p.Sneaking() { - if act, ok := b.(block.SneakingActivatable); ok { - if useCtx := p.useContext(); act.SneakingActivate(pos, face, p.World(), p, useCtx) { - p.SetHeldItems(p.subtractItem(p.damageItem(i, useCtx.Damage), useCtx.CountSub), left) - p.addNewItem(useCtx) - return - } - } - } if i.Empty() { return } diff --git a/server/player/type.go b/server/player/type.go index b7f846b33..d27da0c5b 100644 --- a/server/player/type.go +++ b/server/player/type.go @@ -43,18 +43,20 @@ func (conf Config) Apply(data *world.EntityData) { experience: entity.NewExperienceManager(), effects: entity.NewEffectManager(), locale: locale, - breathing: true, cooldowns: make(map[string]time.Time), mc: &entity.MovementComputer{Gravity: 0.08, Drag: 0.02, DragBeforeGravity: true}, heldSlot: new(uint32), gameMode: conf.GameMode, skin: conf.Skin, - airSupplyTicks: 300, - maxAirSupplyTicks: 300, enchantSeed: rand.Int63(), - scale: 1.0, s: conf.Session, h: NopHandler{}, + speed: 0.1, + flightSpeed: 0.05, + scale: 1.0, + airSupplyTicks: 300, + maxAirSupplyTicks: 300, + breathing: true, } } diff --git a/server/session/handler_player_auth_input.go b/server/session/handler_player_auth_input.go index 8bc9e25ce..19adc2473 100644 --- a/server/session/handler_player_auth_input.go +++ b/server/session/handler_player_auth_input.go @@ -124,10 +124,10 @@ func (h PlayerAuthInputHandler) handleInputFlags(flags uint64, s *Session, c Con c.Jump() } if flags&packet.InputFlagStartCrawling != 0 { - s.c.StartCrawling() + c.StartCrawling() } if flags&packet.InputFlagStopCrawling != 0 { - s.c.StopCrawling() + c.StopCrawling() } if flags&packet.InputFlagMissedSwing != 0 { s.swingingArm.Store(true)