Skip to content

Commit

Permalink
Merge branch 'refs/heads/master' into feature/dynamichashes
Browse files Browse the repository at this point in the history
# Conflicts:
#	server/block/hash.go
  • Loading branch information
TwistedAsylumMC committed Sep 2, 2024
2 parents b886b4b + e99ffb8 commit 16d27a7
Show file tree
Hide file tree
Showing 35 changed files with 669 additions and 221 deletions.
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ toolchain go1.22.1
require (
github.com/brentp/intintmap v0.0.0-20190211203843-30dc0ade9af9
github.com/cespare/xxhash/v2 v2.2.0
github.com/df-mc/atomic v1.10.0
github.com/df-mc/goleveldb v1.1.9
github.com/df-mc/worldupgrader v1.0.16
github.com/go-gl/mathgl v1.1.0
Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/df-mc/atomic v1.10.0 h1:0ZuxBKwR/hxcFGorKiHIp+hY7hgY+XBTzhCYD2NqSEg=
github.com/df-mc/atomic v1.10.0/go.mod h1:Gw9rf+rPIbydMjA329Jn4yjd/O2c/qusw3iNp4tFGSc=
github.com/df-mc/goleveldb v1.1.9 h1:ihdosZyy5jkQKrxucTQmN90jq/2lUwQnJZjIYIC/9YU=
github.com/df-mc/goleveldb v1.1.9/go.mod h1:+NHCup03Sci5q84APIA21z3iPZCuk6m6ABtg4nANCSk=
github.com/df-mc/worldupgrader v1.0.16 h1:3n9yvLFNCe8IDJnUEliTGbhDvV1frjtPX/y5zl3Q5EE=
Expand Down Expand Up @@ -56,8 +54,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
Expand Down
283 changes: 283 additions & 0 deletions server/block/campfire.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
package block

import (
"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/block/model"
"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"
"math/rand"
"strconv"
"time"
)

// Campfire is a block that can be used to cook food, pacify bees, act as a spread-proof light source, smoke signal or
// damaging trap block.
type Campfire struct {
transparent
bass
sourceWaterDisplacer

// Items represents the items in the campfire that are being cooked.
Items [4]CampfireItem
// Facing represents the direction that the campfire is facing.
Facing cube.Direction
// Extinguished is true if the campfire was extinguished by a water source.
Extinguished bool
// Type represents the type of Campfire, currently there are Normal and Soul campfires.
Type FireType
}

// CampfireItem holds data about the items in the campfire.
type CampfireItem struct {
// Item is a specific item being cooked on top of the campfire.
Item item.Stack
// Time is the countdown of ticks until the food item is cooked (when 0).
Time time.Duration
}

// Model ...
func (Campfire) Model() world.BlockModel {
return model.Campfire{}
}

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

// BreakInfo ...
func (c Campfire) BreakInfo() BreakInfo {
return newBreakInfo(2, alwaysHarvestable, axeEffective, func(t item.Tool, enchantments []item.Enchantment) []item.Stack {
var drops []item.Stack
if hasSilkTouch(enchantments) {
drops = append(drops, item.NewStack(c, 1))
} else {
switch c.Type {
case NormalFire():
drops = append(drops, item.NewStack(item.Charcoal{}, 2))
case SoulFire():
drops = append(drops, item.NewStack(SoulSoil{}, 1))
}
}
for _, v := range c.Items {
if !v.Item.Empty() {
drops = append(drops, v.Item)
}
}
return drops
})
}

// LightEmissionLevel ...
func (c Campfire) LightEmissionLevel() uint8 {
if c.Extinguished {
return 0
}
return c.Type.LightLevel()
}

// Ignite ...
func (c Campfire) Ignite(pos cube.Pos, w *world.World, _ world.Entity) bool {
w.PlaySound(pos.Vec3(), sound.Ignite{})
if !c.Extinguished {
return false
}
if _, ok := w.Liquid(pos); ok {
return false
}

c.Extinguished = false
w.SetBlock(pos, c, nil)
return true
}

// Splash ...
func (c Campfire) Splash(w *world.World, pos cube.Pos) {
if c.Extinguished {
return
}

c.extinguish(pos, w)
}

// extinguish extinguishes the campfire.
func (c Campfire) extinguish(pos cube.Pos, w *world.World) {
w.PlaySound(pos.Vec3Centre(), sound.FireExtinguish{})
c.Extinguished = true

for i := range c.Items {
c.Items[i].Time = time.Second * 30
}

w.SetBlock(pos, c, nil)
}

// Activate ...
func (c Campfire) Activate(pos cube.Pos, _ cube.Face, w *world.World, u item.User, ctx *item.UseContext) bool {
held, _ := u.HeldItems()
if held.Empty() {
return false
}

if _, ok := held.Item().(item.Shovel); ok && !c.Extinguished {
c.extinguish(pos, w)
ctx.DamageItem(1)
return true
}

rawFood, ok := held.Item().(item.Smeltable)
if !ok || !rawFood.SmeltInfo().Food {
return false
}

for i, it := range c.Items {
if it.Item.Empty() {
c.Items[i] = CampfireItem{
Item: held.Grow(-held.Count() + 1),
Time: time.Second * 30,
}

ctx.SubtractFromCount(1)

w.PlaySound(pos.Vec3Centre(), sound.ItemAdd{})
w.SetBlock(pos, c, nil)
return true
}
}
return false
}

// UseOnBlock ...
func (c Campfire) 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, c)
if !used {
return
}
if _, ok := w.Block(pos.Side(cube.FaceDown)).(Campfire); ok {
return false
}
c.Facing = user.Rotation().Direction().Opposite()
place(w, pos, c, user, ctx)
return placed(ctx)
}

// Tick is called to cook the items within the campfire.
func (c Campfire) Tick(_ int64, pos cube.Pos, w *world.World) {
if c.Extinguished {
// Extinguished, do nothing.
return
}
if rand.Float64() <= 0.016 { // Every three or so seconds.
w.PlaySound(pos.Vec3Centre(), sound.CampfireCrackle{})
}

updated := false
for i, it := range c.Items {
if it.Item.Empty() {
continue
}

updated = true
if it.Time > 0 {
c.Items[i].Time = it.Time - time.Millisecond*50
continue
}

if food, ok := it.Item.Item().(item.Smeltable); ok {
dropItem(w, food.SmeltInfo().Product, pos.Vec3Middle())
}
c.Items[i].Item = item.Stack{}
}
if updated {
w.SetBlock(pos, c, nil)
}
}

// NeighbourUpdateTick ...
func (c Campfire) NeighbourUpdateTick(pos, _ cube.Pos, w *world.World) {
_, ok := w.Liquid(pos)
liquid, okTwo := w.Liquid(pos.Side(cube.FaceUp))
if (ok || (okTwo && liquid.LiquidType() == "water")) && !c.Extinguished {
c.extinguish(pos, w)
}
}

// EntityInside ...
func (c Campfire) EntityInside(pos cube.Pos, w *world.World, e world.Entity) {
if flammable, ok := e.(flammableEntity); ok {
if flammable.OnFireDuration() > 0 && c.Extinguished {
c.Extinguished = false
w.PlaySound(pos.Vec3(), sound.Ignite{})
w.SetBlock(pos, c, nil)
}
if !c.Extinguished {
if l, ok := e.(livingEntity); ok && !l.AttackImmune() {
l.Hurt(c.Type.Damage(), FireDamageSource{})
}
}
}
}

// EncodeNBT ...
func (c Campfire) EncodeNBT() map[string]any {
m := map[string]any{"id": "Campfire"}
for i, v := range c.Items {
id := strconv.Itoa(i + 1)
if !v.Item.Empty() {
m["Item"+id] = nbtconv.WriteItem(v.Item, true)
m["ItemTime"+id] = uint8(v.Time.Milliseconds() / 50)
}
}
return m
}

// DecodeNBT ...
func (c Campfire) DecodeNBT(data map[string]any) any {
for i := 0; i < 4; i++ {
id := strconv.Itoa(i + 1)
c.Items[i] = CampfireItem{
Item: nbtconv.MapItem(data, "Item"+id),
Time: time.Duration(nbtconv.Int16(data, "ItemTime"+id)) * time.Millisecond * 50,
}
}
return c
}

// EncodeItem ...
func (c Campfire) EncodeItem() (name string, meta int16) {
switch c.Type {
case NormalFire():
return "minecraft:campfire", 0
case SoulFire():
return "minecraft:soul_campfire", 0
}
panic("invalid fire type")
}

// EncodeBlock ...
func (c Campfire) EncodeBlock() (name string, properties map[string]any) {
switch c.Type {
case NormalFire():
name = "minecraft:campfire"
case SoulFire():
name = "minecraft:soul_campfire"
}
return name, map[string]any{
"minecraft:cardinal_direction": c.Facing.String(),
"extinguished": c.Extinguished,
}
}

// allCampfires ...
func allCampfires() (campfires []world.Block) {
for _, d := range cube.Directions() {
for _, f := range FireTypes() {
campfires = append(campfires, Campfire{Facing: d, Type: f, Extinguished: true})
campfires = append(campfires, Campfire{Facing: d, Type: f})
}
}
return campfires
}
8 changes: 4 additions & 4 deletions server/block/ender_chest.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package block

import (
"github.com/df-mc/atomic"
"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/item"
"github.com/df-mc/dragonfly/server/item/inventory"
"github.com/df-mc/dragonfly/server/world"
"github.com/df-mc/dragonfly/server/world/sound"
"github.com/go-gl/mathgl/mgl64"
"sync/atomic"
)

// enderChestOwner represents an entity that has an ender chest inventory.
Expand All @@ -32,7 +32,7 @@ type EnderChest struct {

// NewEnderChest creates a new initialised ender chest.
func NewEnderChest() EnderChest {
return EnderChest{viewers: atomic.NewInt64(0)}
return EnderChest{}
}

// BreakInfo ...
Expand Down Expand Up @@ -75,7 +75,7 @@ func (c EnderChest) Activate(pos cube.Pos, _ cube.Face, _ *world.World, u item.U

// AddViewer ...
func (c EnderChest) AddViewer(w *world.World, pos cube.Pos) {
if c.viewers.Inc() == 1 {
if c.viewers.Add(1) == 1 {
c.open(w, pos)
}
}
Expand All @@ -85,7 +85,7 @@ func (c EnderChest) RemoveViewer(w *world.World, pos cube.Pos) {
if c.viewers.Load() == 0 {
return
}
if c.viewers.Dec() == 0 {
if c.viewers.Add(-1) == 0 {
c.close(w, pos)
}
}
Expand Down
6 changes: 5 additions & 1 deletion server/block/farmland.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package block

import (
"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/event"
"github.com/df-mc/dragonfly/server/world"
"math/rand"
)
Expand Down Expand Up @@ -72,7 +73,10 @@ func (f Farmland) hydrated(pos cube.Pos, w *world.World) bool {
func (f Farmland) EntityLand(pos cube.Pos, w *world.World, e world.Entity, distance *float64) {
if living, ok := e.(livingEntity); ok {
if fall, ok := living.(fallDistanceEntity); ok && rand.Float64() < fall.FallDistance()-0.5 {
w.SetBlock(pos, Dirt{}, nil)
ctx := event.C()
if w.Handler().HandleCropTrample(ctx, pos); !ctx.Cancelled() {
w.SetBlock(pos, Dirt{}, nil)
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion server/block/froglight.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (f Froglight) EncodeItem() (name string, meta int16) {

// EncodeBlock ...
func (f Froglight) EncodeBlock() (name string, properties map[string]any) {
return "minecraft:" + f.Type.String() + "_froglight", map[string]any{"axis": f.Axis.String()}
return "minecraft:" + f.Type.String() + "_froglight", map[string]any{"pillar_axis": f.Axis.String()}
}

// allFrogLight ...
Expand Down
Loading

0 comments on commit 16d27a7

Please sign in to comment.