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

     1  package block
     2  
     3  import (
     4  	"github.com/df-mc/dragonfly/server/block/cube"
     5  	"github.com/df-mc/dragonfly/server/block/model"
     6  	"github.com/df-mc/dragonfly/server/item"
     7  	"github.com/df-mc/dragonfly/server/world"
     8  	"github.com/go-gl/mathgl/mgl64"
     9  )
    10  
    11  // Lantern is a light emitting block.
    12  type Lantern struct {
    13  	transparent
    14  	sourceWaterDisplacer
    15  
    16  	// Hanging determines if a lantern is hanging off a block.
    17  	Hanging bool
    18  	// Type of fire lighting the lantern.
    19  	Type FireType
    20  }
    21  
    22  // Model ...
    23  func (l Lantern) Model() world.BlockModel {
    24  	return model.Lantern{Hanging: l.Hanging}
    25  }
    26  
    27  // NeighbourUpdateTick ...
    28  func (l Lantern) NeighbourUpdateTick(pos, _ cube.Pos, w *world.World) {
    29  	if l.Hanging {
    30  		up := pos.Side(cube.FaceUp)
    31  		if _, ok := w.Block(up).(Chain); !ok && !w.Block(up).Model().FaceSolid(up, cube.FaceDown, w) {
    32  			w.SetBlock(pos, nil, nil)
    33  			dropItem(w, item.NewStack(l, 1), pos.Vec3Centre())
    34  		}
    35  	} else {
    36  		down := pos.Side(cube.FaceDown)
    37  		if !w.Block(down).Model().FaceSolid(down, cube.FaceUp, w) {
    38  			w.SetBlock(pos, nil, nil)
    39  			dropItem(w, item.NewStack(l, 1), pos.Vec3Centre())
    40  		}
    41  	}
    42  }
    43  
    44  // LightEmissionLevel ...
    45  func (l Lantern) LightEmissionLevel() uint8 {
    46  	return l.Type.LightLevel()
    47  }
    48  
    49  // UseOnBlock ...
    50  func (l Lantern) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, user item.User, ctx *item.UseContext) bool {
    51  	pos, face, used := firstReplaceable(w, pos, face, l)
    52  	if !used {
    53  		return false
    54  	}
    55  	if face == cube.FaceDown {
    56  		upPos := pos.Side(cube.FaceUp)
    57  		if _, ok := w.Block(upPos).(Chain); !ok && !w.Block(upPos).Model().FaceSolid(upPos, cube.FaceDown, w) {
    58  			face = cube.FaceUp
    59  		}
    60  	}
    61  	if face != cube.FaceDown {
    62  		downPos := pos.Side(cube.FaceDown)
    63  		if !w.Block(downPos).Model().FaceSolid(downPos, cube.FaceUp, w) {
    64  			return false
    65  		}
    66  	}
    67  	l.Hanging = face == cube.FaceDown
    68  
    69  	place(w, pos, l, user, ctx)
    70  	return placed(ctx)
    71  }
    72  
    73  // SideClosed ...
    74  func (l Lantern) SideClosed(cube.Pos, cube.Pos, *world.World) bool {
    75  	return false
    76  }
    77  
    78  // BreakInfo ...
    79  func (l Lantern) BreakInfo() BreakInfo {
    80  	return newBreakInfo(5, pickaxeHarvestable, pickaxeEffective, oneOf(l))
    81  }
    82  
    83  // EncodeItem ...
    84  func (l Lantern) EncodeItem() (name string, meta int16) {
    85  	switch l.Type {
    86  	case NormalFire():
    87  		return "minecraft:lantern", 0
    88  	case SoulFire():
    89  		return "minecraft:soul_lantern", 0
    90  	}
    91  	panic("invalid fire type")
    92  }
    93  
    94  // EncodeBlock ...
    95  func (l Lantern) EncodeBlock() (name string, properties map[string]any) {
    96  	switch l.Type {
    97  	case NormalFire():
    98  		return "minecraft:lantern", map[string]any{"hanging": l.Hanging}
    99  	case SoulFire():
   100  		return "minecraft:soul_lantern", map[string]any{"hanging": l.Hanging}
   101  	}
   102  	panic("invalid fire type")
   103  }
   104  
   105  // allLanterns ...
   106  func allLanterns() (lanterns []world.Block) {
   107  	for _, f := range FireTypes() {
   108  		lanterns = append(lanterns, Lantern{Hanging: false, Type: f})
   109  		lanterns = append(lanterns, Lantern{Hanging: true, Type: f})
   110  	}
   111  	return
   112  }