up3
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
Build and deploy / Build (push) Has been cancelled
Build and deploy / Update Contributors (push) Has been cancelled
Build and deploy / Deploy (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Anvil is a model used by anvils.
|
||||
type Anvil struct {
|
||||
// Facing is the direction that the anvil is facing.
|
||||
Facing cube.Direction
|
||||
}
|
||||
|
||||
// BBox ...
|
||||
func (a Anvil) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{full.Stretch(a.Facing.RotateLeft().Face().Axis(), -0.125)}
|
||||
}
|
||||
|
||||
// FaceSolid ...
|
||||
func (Anvil) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Bed is a model used for beds. This model works for both parts of the bed.
|
||||
type Bed struct{}
|
||||
|
||||
// BBox ...
|
||||
func (b Bed) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0, 0, 0, 1, 0.5625, 1)}
|
||||
}
|
||||
|
||||
// FaceSolid ...
|
||||
func (Bed) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// BrewingStand is a model used by brewing stands.
|
||||
type BrewingStand struct{}
|
||||
|
||||
// BBox ...
|
||||
func (b BrewingStand) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{
|
||||
full.ExtendTowards(cube.FaceUp, -0.875),
|
||||
full.Stretch(cube.X, -0.4375).Stretch(cube.Z, -0.4375).ExtendTowards(cube.FaceDown, 0.125),
|
||||
}
|
||||
}
|
||||
|
||||
// FaceSolid ...
|
||||
func (b BrewingStand) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Cactus is the model for a Cactus. It is just barely not a full block, having a slightly reduced width and depth.
|
||||
type Cactus struct{}
|
||||
|
||||
// BBox returns a physics.BBox that is slightly smaller than a full block.
|
||||
func (Cactus) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0.025, 0, 0.025, 0.975, 1, 0.975)}
|
||||
}
|
||||
|
||||
// FaceSolid always returns false.
|
||||
func (Cactus) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Cake is a model used by cake blocks.
|
||||
type Cake struct {
|
||||
// Bites is the amount of bites that were taken from the cake. A cake can have up to 7 bites taken from it, before
|
||||
// being consumed entirely.
|
||||
Bites int
|
||||
}
|
||||
|
||||
// BBox returns an BBox with a size that depends on the amount of bites taken.
|
||||
func (c Cake) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0.0625, 0, 0.0625, 0.9375, 0.5, 0.9375).
|
||||
ExtendTowards(cube.FaceWest, -(float64(c.Bites) / 8))}
|
||||
}
|
||||
|
||||
// FaceSolid always returns false.
|
||||
func (c Cake) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Campfire is the model used by campfires.
|
||||
type Campfire struct{}
|
||||
|
||||
// BBox returns a flat BBox with a height of 0.4375.
|
||||
func (Campfire) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0, 0, 0, 1, 0.4375, 1)}
|
||||
}
|
||||
|
||||
// FaceSolid returns true if the face is down.
|
||||
func (Campfire) FaceSolid(_ cube.Pos, face cube.Face, _ world.BlockSource) bool {
|
||||
return face == cube.FaceDown
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Carpet is a model for carpet-like extremely thin blocks.
|
||||
type Carpet struct{}
|
||||
|
||||
// BBox returns a flat BBox with a width of 0.0625.
|
||||
func (Carpet) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0, 0, 0, 1, 0.0625, 1)}
|
||||
}
|
||||
|
||||
// FaceSolid always returns false.
|
||||
func (Carpet) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Chain is a model used by chain blocks.
|
||||
type Chain struct {
|
||||
// Axis is the axis which the chain faces.
|
||||
Axis cube.Axis
|
||||
}
|
||||
|
||||
// BBox ...
|
||||
func (c Chain) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0.40625, 0.40625, 0.40625, 0.59375, 0.59375, 0.59375).Stretch(c.Axis, 0.40625)}
|
||||
}
|
||||
|
||||
// FaceSolid ...
|
||||
func (Chain) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Chest is the model of a chest. It is just barely not a full block, having a slightly reduced with on all
|
||||
// axes.
|
||||
type Chest struct{}
|
||||
|
||||
// BBox returns a physics.BBox that is slightly smaller than a full block.
|
||||
func (Chest) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0.025, 0, 0.025, 0.975, 0.95, 0.975)}
|
||||
}
|
||||
|
||||
// FaceSolid always returns false.
|
||||
func (Chest) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// CocoaBean is a model used by cocoa bean blocks.
|
||||
type CocoaBean struct {
|
||||
// Facing is the face that the cocoa bean faces. It is the opposite of the face that the CocoaBean is attached to.
|
||||
Facing cube.Direction
|
||||
// Age is the age of the CocoaBean. The age influences the size of the CocoaBean. The maximum age value of a cocoa
|
||||
// bean is 3.
|
||||
Age int
|
||||
}
|
||||
|
||||
// BBox returns a single physics.BBox whose size depends on the age of the CocoaBean.
|
||||
func (c CocoaBean) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{full.
|
||||
Stretch(c.Facing.RotateRight().Face().Axis(), -(6-float64(c.Age))/16).
|
||||
ExtendTowards(cube.FaceUp, -0.25).
|
||||
ExtendTowards(cube.FaceDown, -((7-float64(c.Age)*2)/16)).
|
||||
ExtendTowards(c.Facing.Face(), -0.0625).
|
||||
ExtendTowards(c.Facing.Opposite().Face(), -((11 - float64(c.Age)*2) / 16))}
|
||||
}
|
||||
|
||||
// FaceSolid always returns false.
|
||||
func (c CocoaBean) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Composter is a model used by composter blocks. It is solid on all sides apart from the top, and the height of the
|
||||
// inside area depends on the level of compost inside the composter.
|
||||
type Composter struct {
|
||||
// Level is the level of compost inside the composter.
|
||||
Level int
|
||||
}
|
||||
|
||||
// BBox ...
|
||||
func (c Composter) BBox(_ cube.Pos, _ world.BlockSource) []cube.BBox {
|
||||
compostHeight := math.Abs(math.Min(float64(c.Level), 7)*0.125 - 0.0625)
|
||||
return []cube.BBox{
|
||||
cube.Box(0, 0, 0, 1, 1, 0.125),
|
||||
cube.Box(0, 0, 0.875, 1, 1, 1),
|
||||
cube.Box(0.875, 0, 0, 1, 1, 1),
|
||||
cube.Box(0, 0, 0, 0.125, 1, 1),
|
||||
cube.Box(0.125, 0, 0.125, 0.875, 0.125+compostHeight, 0.875),
|
||||
}
|
||||
}
|
||||
|
||||
// FaceSolid returns true for all faces other than the top.
|
||||
func (Composter) FaceSolid(_ cube.Pos, face cube.Face, _ world.BlockSource) bool {
|
||||
return face != cube.FaceUp
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// DecoratedPot is the model for a DecoratedPot. It is just barely not a full block, having a slightly reduced width and
|
||||
// depth.
|
||||
type DecoratedPot struct{}
|
||||
|
||||
// BBox returns a physics.BBox that is slightly smaller than a full block.
|
||||
func (DecoratedPot) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0.025, 0, 0.025, 0.975, 1, 0.975)}
|
||||
}
|
||||
|
||||
// FaceSolid always returns true for the top and bottom face, and false for all other faces.
|
||||
func (DecoratedPot) FaceSolid(_ cube.Pos, face cube.Face, _ world.BlockSource) bool {
|
||||
return face.Axis() == cube.Y
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// Package model has world.BlockModel implementations for each world.Block implementation in the block package. These
|
||||
// models may be reused by blocks that share the same model.
|
||||
// Some block models require additional fields and knowledge about the surrounding blocks to calculate the correct
|
||||
// model.
|
||||
package model
|
||||
@@ -0,0 +1,34 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Door is a model used for doors. It has no solid faces and a bounding box that changes depending on
|
||||
// the direction of the door, whether it is open, and the side of its hinge.
|
||||
type Door struct {
|
||||
// Facing is the direction that the door is facing when closed.
|
||||
Facing cube.Direction
|
||||
// Open specifies if the Door is open. The direction it opens towards depends on the Right field.
|
||||
Open bool
|
||||
// Right specifies the attachment side of the door and, with that, the direction it opens in.
|
||||
Right bool
|
||||
}
|
||||
|
||||
// BBox returns a physics.BBox that depends on if the Door is open, what direction it is facing and whether it is
|
||||
// attached to the right/left side of a block.
|
||||
func (d Door) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
if d.Open {
|
||||
if d.Right {
|
||||
return []cube.BBox{full.ExtendTowards(d.Facing.RotateLeft().Face(), -0.8125)}
|
||||
}
|
||||
return []cube.BBox{full.ExtendTowards(d.Facing.RotateRight().Face(), -0.8125)}
|
||||
}
|
||||
return []cube.BBox{full.ExtendTowards(d.Facing.Face(), -0.8125)}
|
||||
}
|
||||
|
||||
// FaceSolid always returns false.
|
||||
func (d Door) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Empty is a model that is completely empty. It has no collision boxes or solid faces.
|
||||
type Empty struct{}
|
||||
|
||||
// BBox returns an empty slice.
|
||||
func (Empty) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return nil
|
||||
}
|
||||
|
||||
// FaceSolid always returns false.
|
||||
func (Empty) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// EnchantingTable is a model used by enchanting tables.
|
||||
type EnchantingTable struct{}
|
||||
|
||||
// BBox ...
|
||||
func (EnchantingTable) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0, 0, 0, 1, 0.75, 1)}
|
||||
}
|
||||
|
||||
// FaceSolid ...
|
||||
func (EnchantingTable) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// EndRod is a model used by end rod blocks.
|
||||
type EndRod struct {
|
||||
// Axis is the axis which the end rod faces.
|
||||
Axis cube.Axis
|
||||
}
|
||||
|
||||
// BBox ...
|
||||
func (e EndRod) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0.375, 0.375, 0.375, 0.625, 0.625, 0.625).Stretch(e.Axis, 0.375)}
|
||||
}
|
||||
|
||||
// FaceSolid ...
|
||||
func (EndRod) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Fence is a model used by fences of any type. It can attach to blocks with solid faces and other fences of the same
|
||||
// type and has a model height just slightly over 1.
|
||||
type Fence struct {
|
||||
// Wood specifies if the Fence is made from wood. This field is used to check if two fences are able to attach to
|
||||
// each other.
|
||||
Wood bool
|
||||
}
|
||||
|
||||
const (
|
||||
fenceHeight = 1.5
|
||||
fenceInset = 0.375
|
||||
)
|
||||
|
||||
// BBox returns multiple physics.BBox depending on how many connections it has with the surrounding blocks.
|
||||
func (f Fence) BBox(pos cube.Pos, s world.BlockSource) []cube.BBox {
|
||||
boxes := make([]cube.BBox, 0, 2)
|
||||
|
||||
connectWest, connectEast := f.checkConnection(pos, cube.FaceWest, s), f.checkConnection(pos, cube.FaceEast, s)
|
||||
connectNorth, connectSouth := f.checkConnection(pos, cube.FaceNorth, s), f.checkConnection(pos, cube.FaceSouth, s)
|
||||
|
||||
// Check if we have any connections on the Z axis
|
||||
if connectWest || connectEast {
|
||||
sideBox := cube.Box(0, 0, 0, 1, fenceHeight, 1).Stretch(cube.Z, -fenceInset)
|
||||
if connectWest {
|
||||
boxes = append(boxes, sideBox.ExtendTowards(cube.FaceEast, -fenceInset))
|
||||
}
|
||||
if connectEast {
|
||||
boxes = append(boxes, sideBox.ExtendTowards(cube.FaceWest, -fenceInset))
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have any connections on the X axis
|
||||
if connectNorth || connectSouth {
|
||||
sideBox := cube.Box(0, 0, 0, 1, fenceHeight, 1).Stretch(cube.X, -fenceInset)
|
||||
if connectNorth {
|
||||
boxes = append(boxes, sideBox.ExtendTowards(cube.FaceSouth, -fenceInset))
|
||||
}
|
||||
if connectSouth {
|
||||
boxes = append(boxes, sideBox.ExtendTowards(cube.FaceNorth, -fenceInset))
|
||||
}
|
||||
}
|
||||
|
||||
// If no connections, create a center post box
|
||||
if len(boxes) == 0 {
|
||||
boxes = append(boxes, cube.Box(fenceInset, 0, fenceInset, 1-fenceInset, fenceHeight, 1-fenceInset))
|
||||
}
|
||||
|
||||
return boxes
|
||||
}
|
||||
|
||||
// FaceSolid returns true if the face is cube.FaceDown or cube.FaceUp.
|
||||
func (f Fence) FaceSolid(_ cube.Pos, face cube.Face, _ world.BlockSource) bool {
|
||||
return face == cube.FaceDown || face == cube.FaceUp
|
||||
}
|
||||
|
||||
// checkConnection checks if the block at the given position and face has a connection to the current fence block.
|
||||
func (f Fence) checkConnection(pos cube.Pos, face cube.Face, src world.BlockSource) bool {
|
||||
sidePos := pos.Side(face)
|
||||
sideBlock := src.Block(sidePos)
|
||||
if fence, ok := sideBlock.Model().(Fence); ok && fence.Wood == f.Wood {
|
||||
return true
|
||||
}
|
||||
if sideBlock.Model().FaceSolid(sidePos, face.Opposite(), src) {
|
||||
return true
|
||||
}
|
||||
_, ok := sideBlock.Model().(FenceGate)
|
||||
return ok
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// FenceGate is a model used by fence gates. The model is completely zero-ed when the FenceGate is opened.
|
||||
type FenceGate struct {
|
||||
// Facing is the facing direction of the FenceGate. A fence gate can only be opened in this direction or the
|
||||
// direction opposite to it.
|
||||
Facing cube.Direction
|
||||
// Open specifies if the FenceGate is open. In this case, BBox returns an empty slice.
|
||||
Open bool
|
||||
}
|
||||
|
||||
// BBox returns up to one physics.BBox depending on the facing direction of the FenceGate and whether it is open.
|
||||
func (f FenceGate) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
if f.Open {
|
||||
return nil
|
||||
}
|
||||
return []cube.BBox{cube.Box(0, 0, 0, 1, 1.5, 1).Stretch(f.Facing.Face().Axis(), -0.375)}
|
||||
}
|
||||
|
||||
// FaceSolid always returns false.
|
||||
func (f FenceGate) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Grindstone is a model used by grindstones.
|
||||
type Grindstone struct {
|
||||
// Axis is the axis the grindstone is attached to.
|
||||
Axis cube.Axis
|
||||
}
|
||||
|
||||
// BBox ...
|
||||
func (g Grindstone) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0.125, 0.125, 0.125, 0.825, 0.825, 0.825).Stretch(g.Axis, 0.125)}
|
||||
}
|
||||
|
||||
// FaceSolid always returns false.
|
||||
func (g Grindstone) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Hopper is a model used by hoppers.
|
||||
type Hopper struct{}
|
||||
|
||||
// BBox returns a physics.BBox that spans a full block.
|
||||
func (h Hopper) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
bbox := []cube.BBox{full.ExtendTowards(cube.FaceUp, -0.375)}
|
||||
for _, f := range cube.HorizontalFaces() {
|
||||
bbox = append(bbox, full.ExtendTowards(f, -0.875))
|
||||
}
|
||||
return bbox
|
||||
}
|
||||
|
||||
// FaceSolid only returns true for the top face of the hopper.
|
||||
func (Hopper) FaceSolid(_ cube.Pos, face cube.Face, _ world.BlockSource) bool {
|
||||
return face == cube.FaceUp
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Ladder is the model for a ladder block.
|
||||
type Ladder struct {
|
||||
// Facing is the side opposite to the block the Ladder is currently attached to.
|
||||
Facing cube.Direction
|
||||
}
|
||||
|
||||
// BBox returns one physics.BBox that depends on the facing direction of the Ladder.
|
||||
func (l Ladder) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{full.ExtendTowards(l.Facing.Face(), -0.8125)}
|
||||
}
|
||||
|
||||
// FaceSolid always returns false.
|
||||
func (l Ladder) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Lantern is a model for the lantern block. It can be placed on the ground or hanging from the ceiling.
|
||||
type Lantern struct {
|
||||
// Hanging specifies if the lantern is hanging from a block or if it's placed on the ground.
|
||||
Hanging bool
|
||||
}
|
||||
|
||||
// BBox returns a physics.BBox attached to either the ceiling or to the ground.
|
||||
func (l Lantern) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
if l.Hanging {
|
||||
return []cube.BBox{cube.Box(0.3125, 0.125, 0.3125, 0.6875, 0.625, 0.6875)}
|
||||
}
|
||||
return []cube.BBox{cube.Box(0.3125, 0, 0.3125, 0.6875, 0.5, 0.6875)}
|
||||
}
|
||||
|
||||
// FaceSolid always returns false.
|
||||
func (l Lantern) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Leaves is a model for leaves-like blocks. These blocks have a full collision box, but none of their faces
|
||||
// are solid.
|
||||
type Leaves struct{}
|
||||
|
||||
// BBox returns a physics.BBox that spans a full block.
|
||||
func (Leaves) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{full}
|
||||
}
|
||||
|
||||
// FaceSolid always returns false.
|
||||
func (Leaves) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Lectern is a model used by lecterns.
|
||||
type Lectern struct{}
|
||||
|
||||
// BBox ...
|
||||
func (Lectern) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0, 0, 0, 1, 0.9, 1)}
|
||||
}
|
||||
|
||||
// FaceSolid ...
|
||||
func (Lectern) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// LilyPad is a model for the lily pad block.
|
||||
type LilyPad struct{}
|
||||
|
||||
// BBox ...
|
||||
func (LilyPad) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0.0625, 0, 0.0625, 0.9375, 0.015625, 0.9375)}
|
||||
}
|
||||
|
||||
// FaceSolid ...
|
||||
func (LilyPad) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Skull is a model used by skull blocks.
|
||||
type Skull struct {
|
||||
// Direction is the direction the skull is facing.
|
||||
Direction cube.Face
|
||||
// Hanging specifies if the Skull is hanging on a wall.
|
||||
Hanging bool
|
||||
}
|
||||
|
||||
// BBox ...
|
||||
func (s Skull) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
box := cube.Box(0.25, 0, 0.25, 0.75, 0.5, 0.75)
|
||||
if !s.Hanging {
|
||||
return []cube.BBox{box}
|
||||
}
|
||||
return []cube.BBox{box.TranslateTowards(s.Direction.Opposite(), 0.25).TranslateTowards(cube.FaceUp, 0.25)}
|
||||
}
|
||||
|
||||
// FaceSolid ...
|
||||
func (Skull) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Slab is the model of a slab-like block, which is either a half block or a full block, depending on if the
|
||||
// slab is double.
|
||||
type Slab struct {
|
||||
// Double and Top specify if the Slab is a double slab and if it's in the top slot respectively. If Double is true,
|
||||
// the BBox returned is always a full block.
|
||||
Double, Top bool
|
||||
}
|
||||
|
||||
// BBox returns either a physics.BBox spanning a full block or a half block in the top/bottom part of the block,
|
||||
// depending on the Double and Top fields.
|
||||
func (s Slab) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
if s.Double {
|
||||
return []cube.BBox{full}
|
||||
}
|
||||
if s.Top {
|
||||
return []cube.BBox{cube.Box(0, 0.5, 0, 1, 1, 1)}
|
||||
}
|
||||
return []cube.BBox{cube.Box(0, 0, 0, 1, 0.5, 1)}
|
||||
}
|
||||
|
||||
// FaceSolid returns true if the Slab is double, or if the face is cube.FaceUp when the Top field is true, or if the
|
||||
// face is cube.FaceDown when the Top field is false.
|
||||
func (s Slab) FaceSolid(_ cube.Pos, face cube.Face, _ world.BlockSource) bool {
|
||||
if s.Double {
|
||||
return true
|
||||
} else if s.Top {
|
||||
return face == cube.FaceUp
|
||||
}
|
||||
return face == cube.FaceDown
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Solid is the model of a fully solid block. Blocks with this model, such as stone or wooden planks, have a
|
||||
// 1x1x1 collision box.
|
||||
type Solid struct{}
|
||||
|
||||
// full is a BBox that occupies a full block.
|
||||
var full = cube.Box(0, 0, 0, 1, 1, 1)
|
||||
|
||||
// BBox returns a physics.BBox spanning a full block.
|
||||
func (Solid) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{full}
|
||||
}
|
||||
|
||||
// FaceSolid always returns true.
|
||||
func (Solid) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return true
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
"github.com/go-gl/mathgl/mgl64"
|
||||
)
|
||||
|
||||
// Stair is a model for stair-like blocks. These have different solid sides depending on the direction the
|
||||
// stairs are facing, the surrounding blocks and whether it is upside down or not.
|
||||
type Stair struct {
|
||||
// Facing specifies the direction that the full side of the Stair faces.
|
||||
Facing cube.Direction
|
||||
// UpsideDown turns the Stair upside-down, meaning the full side of the Stair is turned to the top side of the
|
||||
// block.
|
||||
UpsideDown bool
|
||||
}
|
||||
|
||||
// BBox returns a slice of physics.BBox depending on if the Stair is upside down and which direction it is facing.
|
||||
// Additionally, these BBoxs depend on the Stair blocks surrounding this one, which can influence the model.
|
||||
func (s Stair) BBox(pos cube.Pos, bs world.BlockSource) []cube.BBox {
|
||||
b := []cube.BBox{cube.Box(0, 0, 0, 1, 0.5, 1)}
|
||||
if s.UpsideDown {
|
||||
b[0] = cube.Box(0, 0.5, 0, 1, 1, 1)
|
||||
}
|
||||
t := s.cornerType(pos, bs)
|
||||
|
||||
face, oppositeFace := s.Facing.Face(), s.Facing.Opposite().Face()
|
||||
switch t {
|
||||
case noCorner, cornerRightInner, cornerLeftInner:
|
||||
b = append(b, cube.Box(0.5, 0.5, 0.5, 0.5, 1, 0.5).
|
||||
ExtendTowards(face, 0.5).
|
||||
Stretch(s.Facing.RotateRight().Face().Axis(), 0.5))
|
||||
}
|
||||
switch t {
|
||||
case cornerRightOuter:
|
||||
b = append(b, cube.Box(0.5, 0.5, 0.5, 0.5, 1, 0.5).
|
||||
ExtendTowards(face, 0.5).
|
||||
ExtendTowards(s.Facing.RotateLeft().Face(), 0.5))
|
||||
case cornerLeftOuter:
|
||||
b = append(b, cube.Box(0.5, 0.5, 0.5, 0.5, 1, 0.5).
|
||||
ExtendTowards(face, 0.5).
|
||||
ExtendTowards(s.Facing.RotateRight().Face(), 0.5))
|
||||
case cornerRightInner:
|
||||
b = append(b, cube.Box(0.5, 0.5, 0.5, 0.5, 1, 0.5).
|
||||
ExtendTowards(oppositeFace, 0.5).
|
||||
ExtendTowards(s.Facing.RotateRight().Face(), 0.5))
|
||||
case cornerLeftInner:
|
||||
b = append(b, cube.Box(0.5, 0.5, 0.5, 0.5, 1, 0.5).
|
||||
ExtendTowards(oppositeFace, 0.5).
|
||||
ExtendTowards(s.Facing.RotateLeft().Face(), 0.5))
|
||||
}
|
||||
if s.UpsideDown {
|
||||
for i := range b[1:] {
|
||||
b[i+1] = b[i+1].Translate(mgl64.Vec3{0, -0.5})
|
||||
}
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// FaceSolid returns true for all faces of the Stair that are completely filled.
|
||||
func (s Stair) FaceSolid(pos cube.Pos, face cube.Face, bs world.BlockSource) bool {
|
||||
// Stairs always have a closed side at the top or bottom based on their orientation.
|
||||
if (face == cube.FaceUp && s.UpsideDown) || (face == cube.FaceDown && !s.UpsideDown) {
|
||||
return true
|
||||
}
|
||||
|
||||
switch t := s.cornerType(pos, bs); t {
|
||||
case cornerRightOuter, cornerLeftOuter:
|
||||
// Small corner blocks, they do not block water flowing out horizontally.
|
||||
return false
|
||||
case noCorner:
|
||||
// Not a corner, so only block directly behind the stairs.
|
||||
return s.Facing.Face() == face
|
||||
case cornerRightInner:
|
||||
return face == s.Facing.RotateRight().Face() || face == s.Facing.Face()
|
||||
default:
|
||||
return face == s.Facing.RotateLeft().Face() || face == s.Facing.Face()
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
noCorner = iota
|
||||
cornerRightInner
|
||||
cornerLeftInner
|
||||
cornerRightOuter
|
||||
cornerLeftOuter
|
||||
)
|
||||
|
||||
// cornerType returns the type of the corner that the stairs form, or 0 if it does not form a corner with any
|
||||
// other stairs.
|
||||
func (s Stair) cornerType(pos cube.Pos, bs world.BlockSource) uint8 {
|
||||
rotatedFacing := s.Facing.RotateRight()
|
||||
if closedSide, ok := bs.Block(pos.Side(s.Facing.Face())).Model().(Stair); ok && closedSide.UpsideDown == s.UpsideDown {
|
||||
if closedSide.Facing == rotatedFacing {
|
||||
return cornerLeftOuter
|
||||
} else if closedSide.Facing == rotatedFacing.Opposite() {
|
||||
// This will only form a corner if there is not a stair on the right of this one with the same
|
||||
// direction.
|
||||
if side, ok := bs.Block(pos.Side(s.Facing.RotateRight().Face())).Model().(Stair); !ok || side.Facing != s.Facing || side.UpsideDown != s.UpsideDown {
|
||||
return cornerRightOuter
|
||||
}
|
||||
return noCorner
|
||||
}
|
||||
}
|
||||
if openSide, ok := bs.Block(pos.Side(s.Facing.Opposite().Face())).Model().(Stair); ok && openSide.UpsideDown == s.UpsideDown {
|
||||
if openSide.Facing == rotatedFacing {
|
||||
// This will only form a corner if there is not a stair on the right of this one with the same
|
||||
// direction.
|
||||
if side, ok := bs.Block(pos.Side(s.Facing.RotateRight().Face())).Model().(Stair); !ok || side.Facing != s.Facing || side.UpsideDown != s.UpsideDown {
|
||||
return cornerRightInner
|
||||
}
|
||||
} else if openSide.Facing == rotatedFacing.Opposite() {
|
||||
return cornerLeftInner
|
||||
}
|
||||
}
|
||||
return noCorner
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Stonecutter is a model used by stonecutters.
|
||||
type Stonecutter struct{}
|
||||
|
||||
// BBox ...
|
||||
func (Stonecutter) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{cube.Box(0, 0, 0, 1, 0.5625, 1)}
|
||||
}
|
||||
|
||||
// FaceSolid ...
|
||||
func (Stonecutter) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Thin is a model for thin, partial blocks such as a glass pane or an iron bar. It changes its bounding box depending
|
||||
// on solid faces next to it.
|
||||
type Thin struct{}
|
||||
|
||||
const (
|
||||
thinHeight = 1
|
||||
thinInset = 7.0 / 16.0
|
||||
)
|
||||
|
||||
// BBox returns a slice of physics.BBox that depends on the blocks surrounding the Thin block. Thin blocks can connect
|
||||
// to any other Thin block, wall or solid faces of other blocks.
|
||||
func (t Thin) BBox(pos cube.Pos, s world.BlockSource) []cube.BBox {
|
||||
boxes := make([]cube.BBox, 0, 2)
|
||||
|
||||
// Check if we have any connections on the Z axis
|
||||
connectWest, connectEast := t.checkConnection(pos, cube.FaceWest, s), t.checkConnection(pos, cube.FaceEast, s)
|
||||
if connectWest || connectEast {
|
||||
box := cube.Box(0, 0, 0, 1, thinHeight, 1).Stretch(cube.Z, -thinInset)
|
||||
if !connectWest {
|
||||
box = box.ExtendTowards(cube.FaceWest, -thinInset)
|
||||
} else if !connectEast {
|
||||
box = box.ExtendTowards(cube.FaceEast, -thinInset)
|
||||
}
|
||||
boxes = append(boxes, box)
|
||||
}
|
||||
|
||||
// Check if we have any connections on the X axis
|
||||
connectNorth, connectSouth := t.checkConnection(pos, cube.FaceNorth, s), t.checkConnection(pos, cube.FaceSouth, s)
|
||||
if connectNorth || connectSouth {
|
||||
box := cube.Box(0, 0, 0, 1, thinHeight, 1).Stretch(cube.X, -thinInset)
|
||||
if !connectNorth {
|
||||
box = box.ExtendTowards(cube.FaceNorth, -thinInset)
|
||||
} else if !connectSouth {
|
||||
box = box.ExtendTowards(cube.FaceSouth, -thinInset)
|
||||
}
|
||||
boxes = append(boxes, box)
|
||||
}
|
||||
|
||||
// If no connections, create a center post box
|
||||
if len(boxes) == 0 {
|
||||
boxes = append(boxes, cube.Box(0, 0, 0, 1, thinHeight, 1).Stretch(cube.X, -thinInset).Stretch(cube.Z, -thinInset))
|
||||
}
|
||||
|
||||
return boxes
|
||||
}
|
||||
|
||||
// FaceSolid returns true if the face passed is cube.FaceDown.
|
||||
func (t Thin) FaceSolid(_ cube.Pos, face cube.Face, _ world.BlockSource) bool {
|
||||
return face == cube.FaceDown
|
||||
}
|
||||
|
||||
// checkConnection checks if the block at the given position and face has a connection to the current thin block.
|
||||
func (t Thin) checkConnection(pos cube.Pos, face cube.Face, s world.BlockSource) bool {
|
||||
sidePos := pos.Side(face)
|
||||
sideBlock := s.Block(sidePos)
|
||||
_, isThin := sideBlock.Model().(Thin)
|
||||
_, isWall := sideBlock.Model().(Wall)
|
||||
return isThin || isWall || sideBlock.Model().FaceSolid(sidePos, face.Opposite(), s)
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// TilledGrass is a model used for grass that has been tilled in some way, such as dirt paths and farmland.
|
||||
type TilledGrass struct{}
|
||||
|
||||
// BBox returns a physics.BBox that spans an entire block.
|
||||
func (TilledGrass) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
return []cube.BBox{full.ExtendTowards(cube.FaceUp, -0.0625)}
|
||||
}
|
||||
|
||||
// FaceSolid always returns true.
|
||||
func (TilledGrass) FaceSolid(cube.Pos, cube.Face, world.BlockSource) bool {
|
||||
return true
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Trapdoor is a model used for trapdoors. It has no solid faces and a bounding box that changes depending on
|
||||
// the direction of the trapdoor.
|
||||
type Trapdoor struct {
|
||||
// Facing is the facing direction of the Trapdoor. In addition to the texture, it influences the direction in which
|
||||
// the Trapdoor is opened.
|
||||
Facing cube.Direction
|
||||
// Open and Top specify if the Trapdoor is opened and if it's in the top or bottom part of a block respectively.
|
||||
Open, Top bool
|
||||
}
|
||||
|
||||
// BBox returns a physics.BBox that depends on the facing direction of the Trapdoor and whether it is open and in the
|
||||
// top part of the block.
|
||||
func (t Trapdoor) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
if t.Open {
|
||||
return []cube.BBox{full.ExtendTowards(t.Facing.Face(), -0.8125)}
|
||||
} else if t.Top {
|
||||
return []cube.BBox{cube.Box(0, 0.8125, 0, 1, 1, 1)}
|
||||
}
|
||||
return []cube.BBox{cube.Box(0, 0, 0, 1, 0.1875, 1)}
|
||||
}
|
||||
|
||||
// FaceSolid returns true if the face is completely filled with the trapdoor.
|
||||
func (t Trapdoor) FaceSolid(_ cube.Pos, face cube.Face, _ world.BlockSource) bool {
|
||||
if t.Open {
|
||||
return t.Facing.Face().Opposite() == face
|
||||
} else if t.Top {
|
||||
return face == cube.FaceUp
|
||||
}
|
||||
return face == cube.FaceDown
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/df-mc/dragonfly/server/block/cube"
|
||||
"github.com/df-mc/dragonfly/server/world"
|
||||
)
|
||||
|
||||
// Wall is a model used by all wall types.
|
||||
type Wall struct {
|
||||
// NorthConnection is the height of the connection for the north direction.
|
||||
NorthConnection float64
|
||||
// EastConnection is the height of the connection for the east direction.
|
||||
EastConnection float64
|
||||
// SouthConnection is the height of the connection for the south direction.
|
||||
SouthConnection float64
|
||||
// WestConnection is the height of the connection for the west direction.
|
||||
WestConnection float64
|
||||
// Post is if the wall is the full height of a block or not.
|
||||
Post bool
|
||||
}
|
||||
|
||||
// BBox ...
|
||||
func (w Wall) BBox(cube.Pos, world.BlockSource) []cube.BBox {
|
||||
postHeight := 0.8125
|
||||
if w.Post {
|
||||
postHeight = 1
|
||||
}
|
||||
boxes := []cube.BBox{cube.Box(0.25, 0, 0.25, 0.75, postHeight, 0.75)}
|
||||
if w.NorthConnection > 0 {
|
||||
boxes = append(boxes, cube.Box(0.25, 0, 0, 0.75, w.NorthConnection, 0.25))
|
||||
}
|
||||
if w.EastConnection > 0 {
|
||||
boxes = append(boxes, cube.Box(0.75, 0, 0.25, 1, w.EastConnection, 0.75))
|
||||
}
|
||||
if w.SouthConnection > 0 {
|
||||
boxes = append(boxes, cube.Box(0.25, 0, 0.75, 0.75, w.SouthConnection, 1))
|
||||
}
|
||||
if w.WestConnection > 0 {
|
||||
boxes = append(boxes, cube.Box(0, 0, 0.25, 0.25, w.WestConnection, 0.75))
|
||||
}
|
||||
return boxes
|
||||
}
|
||||
|
||||
// FaceSolid returns true if the face is in the Y axis.
|
||||
func (w Wall) FaceSolid(_ cube.Pos, face cube.Face, _ world.BlockSource) bool {
|
||||
return face.Axis() == cube.Y
|
||||
}
|
||||
Reference in New Issue
Block a user