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

Introduce entity animations #806

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions server/entity/animation/animation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package animation

// Animation represents an animation & controller that may be attached to an entity.
// Animations and controllers must be defined in a resource pack
type Animation struct {
name, state, controller string
stopCondition string
}

// New returns a new animation that can be attached to an entity. By default no controller or state is sent to the viewer.
// To add a state and controller use WithController and WithState respectively.
func New(animationName string) Animation {
return Animation{
name: animationName,
state: "",
controller: "",
stopCondition: "",
}
}

// Name returns the name of the animation to be played
func (a Animation) Name() string {
return a.name
}

// WithController sets the controller with the specified state.
// The controller must be added in a resource pack
func (a Animation) WithController(controller string) Animation {
a.controller = controller
return a
}

// Controller returns the name of the controller being used. Controller returns an empty string if
// no controller was previously set
func (a Animation) Controller() string {
return a.controller
}

// WithState sets the state to transition to as defined in the controller.
func (a Animation) WithState(state string) Animation {
a.state = state
return a
}

// State returns the current state being played. State returns an empty string if
// no controller was previously set
func (a Animation) State() string {
return a.state
}

// WithStopCondition takes the molang expression and stops the animation if the query passes.
func (a Animation) WithStopCondition(condition string) Animation {
a.stopCondition = condition
return a
}

// StopCondition returns the stop condition. StopCondition returns an empty string if
// no molang expression was set
func (a Animation) StopCondition() string {
return a.stopCondition
}
11 changes: 8 additions & 3 deletions server/session/world.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package session

import (
"github.com/df-mc/dragonfly/server/entity/effect"
"image/color"
"math/rand"
"strings"
"time"

"github.com/df-mc/dragonfly/server/entity/animation"
"github.com/df-mc/dragonfly/server/entity/effect"

"github.com/df-mc/dragonfly/server/block"
"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/entity"
Expand Down Expand Up @@ -915,9 +917,12 @@ func (s *Session) ViewEntityState(e world.Entity) {
}

// ViewEntityAnimation ...
func (s *Session) ViewEntityAnimation(e world.Entity, animationName string) {
func (s *Session) ViewEntityAnimation(e world.Entity, animation animation.Animation) {
s.writePacket(&packet.AnimateEntity{
Animation: animationName,
Animation: animation.Name(),
NextState: animation.State(),
StopCondition: animation.StopCondition(),
Controller: animation.Controller(),
EntityRuntimeIDs: []uint64{
s.entityRuntimeID(e),
},
Expand Down
8 changes: 5 additions & 3 deletions server/world/viewer.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package world

import (
"time"

"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/entity/animation"
"github.com/df-mc/dragonfly/server/world/chunk"
"github.com/go-gl/mathgl/mgl64"
"github.com/google/uuid"
"time"
)

// Viewer is a viewer in the world. It can view changes that are made in the world, such as the addition of
Expand Down Expand Up @@ -48,7 +50,7 @@ type Viewer interface {
// physical appearance, for example when sprinting.
ViewEntityState(e Entity)
// ViewEntityAnimation starts viewing an animation performed by an entity. The animation has to be from a resource pack.
ViewEntityAnimation(e Entity, animationName string)
ViewEntityAnimation(e Entity, animation animation.Animation)
// ViewParticle views a particle spawned at a given position in the world. It is called when a particle,
// for example a block breaking particle, is spawned near the player.
ViewParticle(pos mgl64.Vec3, p Particle)
Expand Down Expand Up @@ -89,7 +91,7 @@ func (NopViewer) ViewEntityItems(Entity) {}
func (NopViewer) ViewEntityArmour(Entity) {}
func (NopViewer) ViewEntityAction(Entity, EntityAction) {}
func (NopViewer) ViewEntityState(Entity) {}
func (NopViewer) ViewEntityAnimation(Entity, string) {}
func (NopViewer) ViewEntityAnimation(Entity, animation.Animation) {}
func (NopViewer) ViewParticle(mgl64.Vec3, Particle) {}
func (NopViewer) ViewSound(mgl64.Vec3, Sound) {}
func (NopViewer) ViewBlockUpdate(cube.Pos, Block, int) {}
Expand Down
17 changes: 16 additions & 1 deletion server/world/world.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package world

import (
"errors"
"github.com/df-mc/goleveldb/leveldb"
"math/rand"
"sync"
"time"

"github.com/df-mc/goleveldb/leveldb"

"github.com/df-mc/atomic"
"github.com/df-mc/dragonfly/server/block/cube"
"github.com/df-mc/dragonfly/server/entity/animation"
"github.com/df-mc/dragonfly/server/event"
"github.com/df-mc/dragonfly/server/internal/sliceutil"
"github.com/df-mc/dragonfly/server/world/chunk"
Expand Down Expand Up @@ -643,6 +645,19 @@ func (w *World) AddParticle(pos mgl64.Vec3, p Particle) {
}
}

// AnimateEntity will start an animation for the specified entity. Viewers that are viewing the entity will be
// played the animation.
func (w *World) AnimateEntity(e Entity, animation animation.Animation) {
// Ignore if no animation name has been given
if animation.Name() == "" {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if animation.Name() == "" {
if len(animation.Name()) == 0 {

return
}

for _, v := range w.Viewers(e.Position()) {
v.ViewEntityAnimation(e, animation)
}
}

// PlaySound plays a sound at a specific position in the world. Viewers of that position will be able to hear
// the sound if they're close enough.
func (w *World) PlaySound(pos mgl64.Vec3, s Sound) {
Expand Down