Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented skull block #396

Merged
merged 8 commits into from
Jul 17, 2022
5 changes: 5 additions & 0 deletions server/block/hash.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 28 additions & 0 deletions server/block/model/skull.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package model

import (
"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/entity/physics"
"github.com/df-mc/dragonfly/server/world"
"github.com/go-gl/mathgl/mgl64"
)

// Skull is a model used by skull blocks.
type Skull struct {
// Direction is the direction the skull is facing.
Direction cube.Face
}

// AABB ...
func (s Skull) AABB(cube.Pos, *world.World) []physics.AABB {
aabb := physics.NewAABB(mgl64.Vec3{0.25, 0, 0.25}, mgl64.Vec3{0.75, 0.5, 0.75})
if s.Direction.Axis() == cube.Y {
return []physics.AABB{aabb}
}
return []physics.AABB{aabb.TranslateTowards(s.Direction.Opposite(), 0.25).TranslateTowards(cube.FaceUp, 0.25)}
}

// FaceSolid ...
func (Skull) FaceSolid(cube.Pos, cube.Face, *world.World) bool {
return false
}
4 changes: 4 additions & 0 deletions server/block/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ func init() {
registerAll(allSeaPickles())
registerAll(allWood())
registerAll(allChains())
registerAll(allSkulls())
}

func init() {
Expand Down Expand Up @@ -333,6 +334,9 @@ func init() {
for _, p := range PrismarineTypes() {
world.RegisterItem(Prismarine{Type: p})
}
for _, s := range SkullTypes() {
world.RegisterItem(Skull{Type: s})
}
}

func registerAll(blocks []world.Block) {
Expand Down
112 changes: 112 additions & 0 deletions server/block/skull.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
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/go-gl/mathgl/mgl64"
)

// TODO: Dragon Heads can be powered by redstone

// Skull is a decorative block. There are six types of skulls: player, zombie, skeleton, wither skeleton, creeper,
// and dragon.
type Skull struct {
transparent

// Type is the type of the skull.
Type SkullType
// Direction is the direction the skull is facing. For skulls placed on the floor, this is cube.FaceUp.
Direction cube.Face
// Rotation is the number of rotations for skulls placed on the floor. There are a total of 16 rotations.
Rotation cube.Orientation
Copy link
Member

@Sandertv Sandertv Jan 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should use the Attachment type. If I'm not mistaken the placement logic of skulls (roughly) matches that of signs.

}

// Helmet ...
func (Skull) Helmet() bool {
return true
}

// DefencePoints ...
func (Skull) DefencePoints() float64 {
return 0
}

// KnockBackResistance ...
func (Skull) KnockBackResistance() float64 {
return 0
}

// Model ...
func (s Skull) Model() world.BlockModel {
return model.Skull{Direction: s.Direction}
}

// UseOnBlock ...
func (s Skull) UseOnBlock(pos cube.Pos, face cube.Face, _ mgl64.Vec3, w *world.World, user item.User, ctx *item.UseContext) (used bool) {
pos, face, used = firstReplaceable(w, pos, face, s)
if !used || face == cube.FaceDown {
return false
}

s.Direction = face
if face == cube.FaceUp {
yaw, _ := user.Rotation()
s.Rotation = cube.OrientationFromYaw(yaw)
}
place(w, pos, s, user, ctx)
return placed(ctx)
}

// CanDisplace ...
func (Skull) CanDisplace(b world.Liquid) bool {
_, water := b.(Water)
return water
}

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

// HasLiquidDrops ...
func (Skull) HasLiquidDrops() bool {
return true
}

// BreakInfo ...
func (s Skull) BreakInfo() BreakInfo {
return newBreakInfo(1, alwaysHarvestable, nothingEffective, oneOf(Skull{Type: s.Type}))
}

// EncodeItem ...
func (s Skull) EncodeItem() (name string, meta int16) {
return "minecraft:skull", int16(s.Type.Uint8())
}

// DecodeNBT ...
func (s Skull) DecodeNBT(data map[string]interface{}) interface{} {
s.Type = SkullType{skull(nbtconv.MapByte(data, "SkullType"))}
s.Rotation = cube.Orientation(nbtconv.MapByte(data, "Rot"))
return s
}

// EncodeNBT ...
func (s Skull) EncodeNBT() map[string]interface{} {
return map[string]interface{}{"id": "Skull", "SkullType": s.Type.Uint8(), "Rot": byte(s.Rotation)}
}

// EncodeBlock ...
func (s Skull) EncodeBlock() (string, map[string]interface{}) {
return "minecraft:skull", map[string]interface{}{"facing_direction": int32(s.Direction), "no_drop_bit": uint8(0)}
}

// allSkulls ...
func allSkulls() (skulls []world.Block) {
for _, f := range cube.Faces() {
skulls = append(skulls, Skull{Direction: f})
}
return
}
109 changes: 109 additions & 0 deletions server/block/skull_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package block

import (
"fmt"
)

// SkullType represents a mob variant of a skull.
type SkullType struct {
skull
}

// SkeletonSkull returns the skull variant for skeletons.
func SkeletonSkull() SkullType {
return SkullType{0}
}

// WitherSkeletonSkull returns the skull variant for wither skeletons.
func WitherSkeletonSkull() SkullType {
return SkullType{1}
}

// ZombieHead returns the skull variant for zombies.
func ZombieHead() SkullType {
return SkullType{2}
}

// PlayerHead returns the skull variant for players.
func PlayerHead() SkullType {
return SkullType{3}
}

// CreeperHead returns the skull variant for creepers.
func CreeperHead() SkullType {
return SkullType{4}
}

// DragonHead returns the skull variant for ender dragons.
func DragonHead() SkullType {
return SkullType{5}
}

// SkullTypes returns all variants of skulls.
func SkullTypes() []SkullType {
return []SkullType{SkeletonSkull(), WitherSkeletonSkull(), ZombieHead(), PlayerHead(), CreeperHead(), DragonHead()}
}

type skull uint8

// Uint8 ...
func (s skull) Uint8() uint8 {
return uint8(s)
}

// Name ...
func (s skull) Name() string {
switch s {
case 0:
return "Skeleton Skull"
case 1:
return "Wither Skeleton Skull"
case 2:
return "Zombie Head"
case 3:
return "Player Head"
case 4:
return "Creeper Head"
case 5:
return "Dragon Head"
}
panic("unknown skull type")
}

// FromString ...
func (s skull) FromString(str string) (interface{}, error) {
switch str {
case "skeleton":
return SkeletonSkull(), nil
case "wither_skeleton":
return WitherSkeletonSkull(), nil
case "zombie":
return ZombieHead(), nil
case "player":
return PlayerHead(), nil
case "creeper":
return CreeperHead(), nil
case "dragon":
return DragonHead(), nil
}
return nil, fmt.Errorf("unexpected skull type '%v', expecting one of 'skeleton', 'wither_skeleton', 'zombie', 'creeper', or 'dragon'", str)
}

// String ...
func (s skull) String() string {
switch s {
case 0:
return "skeleton"
case 1:
return "wither_skeleton"
case 2:
return "zombie"
case 3:
return "player"
case 4:
return "creeper"
case 5:
return "dragon"
}
panic("unknown skull type")
}
19 changes: 19 additions & 0 deletions server/entity/physics/aabb.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,25 @@ func (aabb AABB) Translate(vec mgl64.Vec3) AABB {
return NewAABB(aabb.min.Add(vec), aabb.max.Add(vec))
}

// TranslateTowards moves the entire AABB by x within a given direction.
func (aabb AABB) TranslateTowards(f cube.Face, x float64) AABB {
switch f {
case cube.FaceDown:
return aabb.Translate(mgl64.Vec3{0, -x, 0})
case cube.FaceUp:
return aabb.Translate(mgl64.Vec3{0, x, 0})
case cube.FaceNorth:
return aabb.Translate(mgl64.Vec3{0, 0, -x})
case cube.FaceSouth:
return aabb.Translate(mgl64.Vec3{0, 0, x})
case cube.FaceWest:
return aabb.Translate(mgl64.Vec3{-x, 0, 0})
case cube.FaceEast:
return aabb.Translate(mgl64.Vec3{x, 0, 0})
}
return aabb
}

// IntersectsWith checks if the AABB intersects with another AABB, returning true if this is the case.
func (aabb AABB) IntersectsWith(other AABB) bool {
if other.max[0]-aabb.min[0] > 1e-5 && aabb.max[0]-other.min[0] > 1e-5 {
Expand Down