github.com/df-mc/dragonfly@v0.9.13/server/block/coral.go (about)

     1  package block
     2  
     3  import (
     4  	"github.com/df-mc/dragonfly/server/block/cube"
     5  	"github.com/df-mc/dragonfly/server/item"
     6  	"github.com/df-mc/dragonfly/server/world"
     7  	"github.com/df-mc/dragonfly/server/world/particle"
     8  	"github.com/go-gl/mathgl/mgl64"
     9  	"math/rand"
    10  	"time"
    11  )
    12  
    13  // Coral is a non-solid block that comes in 5 variants.
    14  type Coral struct {
    15  	empty
    16  	transparent
    17  	bassDrum
    18  	sourceWaterDisplacer
    19  
    20  	// Type is the type of coral of the block.
    21  	Type CoralType
    22  	// Dead is whether the coral is dead.
    23  	Dead bool
    24  }
    25  
    26  // UseOnBlock ...
    27  func (c Coral) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, user item.User, ctx *item.UseContext) bool {
    28  	pos, _, used := firstReplaceable(w, pos, face, c)
    29  	if !used {
    30  		return false
    31  	}
    32  	if !w.Block(pos.Side(cube.FaceDown)).Model().FaceSolid(pos.Side(cube.FaceDown), cube.FaceUp, w) {
    33  		return false
    34  	}
    35  	if liquid, ok := w.Liquid(pos); ok {
    36  		if water, ok := liquid.(Water); ok {
    37  			if water.Depth != 8 {
    38  				return false
    39  			}
    40  		}
    41  	}
    42  
    43  	place(w, pos, c, user, ctx)
    44  	return placed(ctx)
    45  }
    46  
    47  // HasLiquidDrops ...
    48  func (c Coral) HasLiquidDrops() bool {
    49  	return false
    50  }
    51  
    52  // SideClosed ...
    53  func (c Coral) SideClosed(cube.Pos, cube.Pos, *world.World) bool {
    54  	return false
    55  }
    56  
    57  // NeighbourUpdateTick ...
    58  func (c Coral) NeighbourUpdateTick(pos, _ cube.Pos, w *world.World) {
    59  	if !w.Block(pos.Side(cube.FaceDown)).Model().FaceSolid(pos.Side(cube.FaceDown), cube.FaceUp, w) {
    60  		w.SetBlock(pos, nil, nil)
    61  		w.AddParticle(pos.Vec3Centre(), particle.BlockBreak{Block: c})
    62  		return
    63  	}
    64  	if c.Dead {
    65  		return
    66  	}
    67  	w.ScheduleBlockUpdate(pos, time.Second*5/2)
    68  }
    69  
    70  // ScheduledTick ...
    71  func (c Coral) ScheduledTick(pos cube.Pos, w *world.World, _ *rand.Rand) {
    72  	if c.Dead {
    73  		return
    74  	}
    75  
    76  	adjacentWater := false
    77  	pos.Neighbours(func(neighbour cube.Pos) {
    78  		if liquid, ok := w.Liquid(neighbour); ok {
    79  			if _, ok := liquid.(Water); ok {
    80  				adjacentWater = true
    81  			}
    82  		}
    83  	}, w.Range())
    84  	if !adjacentWater {
    85  		c.Dead = true
    86  		w.SetBlock(pos, c, nil)
    87  	}
    88  }
    89  
    90  // BreakInfo ...
    91  func (c Coral) BreakInfo() BreakInfo {
    92  	return newBreakInfo(0, alwaysHarvestable, nothingEffective, silkTouchOnlyDrop(c))
    93  }
    94  
    95  // EncodeBlock ...
    96  func (c Coral) EncodeBlock() (name string, properties map[string]any) {
    97  	if c.Dead {
    98  		return "minecraft:dead_" + c.Type.String() + "_coral", nil
    99  	}
   100  	return "minecraft:" + c.Type.String() + "_coral", nil
   101  }
   102  
   103  // EncodeItem ...
   104  func (c Coral) EncodeItem() (name string, meta int16) {
   105  	if c.Dead {
   106  		return "minecraft:dead_" + c.Type.String() + "_coral", 0
   107  	}
   108  	return "minecraft:" + c.Type.String() + "_coral", 0
   109  }
   110  
   111  // allCoral returns a list of all coral block variants
   112  func allCoral() (c []world.Block) {
   113  	f := func(dead bool) {
   114  		for _, t := range CoralTypes() {
   115  			c = append(c, Coral{Type: t, Dead: dead})
   116  		}
   117  	}
   118  	f(true)
   119  	f(false)
   120  	return
   121  }