Skip to content

Commit

Permalink
world/viewer.go: Allow for more complex entity animations to be played (
Browse files Browse the repository at this point in the history
  • Loading branch information
TwistedAsylumMC authored Nov 28, 2024
1 parent f660027 commit 02fa0e8
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 5 deletions.
7 changes: 5 additions & 2 deletions server/session/world.go
Original file line number Diff line number Diff line change
Expand Up @@ -976,9 +976,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, a world.EntityAnimation) {
s.writePacket(&packet.AnimateEntity{
Animation: animationName,
Animation: a.Name(),
NextState: a.NextState(),
StopCondition: a.StopCondition(),
Controller: a.Controller(),
EntityRuntimeIDs: []uint64{
s.entityRuntimeID(e),
},
Expand Down
63 changes: 63 additions & 0 deletions server/world/entity_animation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package world

// EntityAnimation represents an animation that may be played on an entity from an active resource pack on
// the client.
type EntityAnimation struct {
name string
nextState string
controller string
stopCondition string
}

// NewEntityAnimation returns a new animation that can be played on an entity. If no controller or stop
// condition is set, the animation will play for its full duration, including looping. Controllers can be set
// to manage multiple states of animations. It is also possible to use vanilla animations/controllers if they
// work for your entity, i.e. "animation.pig.baby_transform".
func NewEntityAnimation(name string) EntityAnimation {
return EntityAnimation{name: name}
}

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

// Controller returns the name of the controller to be used for the animation.
func (a EntityAnimation) Controller() string {
return a.controller
}

// WithController returns a copy of the EntityAnimation with the provided animation controller. An animation
// controller with the same name must be defined in a resource pack for it to work.
func (a EntityAnimation) WithController(controller string) EntityAnimation {
a.controller = controller
return a
}

// NextState returns the state to transition to after the animation has finished playing within the
// animation controller.
func (a EntityAnimation) NextState() string {
return a.nextState
}

// WithNextState returns a copy of the EntityAnimation with the provided state to transition to after the
// animation has finished playing within the animation controller.
func (a EntityAnimation) WithNextState(state string) EntityAnimation {
a.nextState = state
return a
}

// StopCondition returns the condition that must be met for the animation to stop playing. This is often
// a Molang expression that can be used to query various entity properties to determine when the animation
// should stop playing.
func (a EntityAnimation) StopCondition() string {
return a.stopCondition
}

// WithStopCondition returns a copy of the EntityAnimation with the provided stop condition. The stop condition
// is a Molang expression that can be used to query various entity properties to determine when the animation
// should stop playing.
func (a EntityAnimation) WithStopCondition(condition string) EntityAnimation {
a.stopCondition = condition
return a
}
8 changes: 8 additions & 0 deletions server/world/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,14 @@ func (tx *Tx) AddParticle(pos mgl64.Vec3, p Particle) {
tx.World().addParticle(pos, p)
}

// PlayEntityAnimation plays an animation on an entity in the World. The animation is played for all viewers
// of the entity.
func (tx *Tx) PlayEntityAnimation(e Entity, a EntityAnimation) {
for _, viewer := range tx.World().viewersOf(e.Position()) {
viewer.ViewEntityAnimation(e, a)
}
}

// PlaySound plays a sound at a specific position in the World. Viewers of that
// position will be able to hear the sound if they are close enough.
func (tx *Tx) PlaySound(pos mgl64.Vec3, s Sound) {
Expand Down
6 changes: 3 additions & 3 deletions server/world/viewer.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ type Viewer interface {
// ViewEntityState views the current state of an Entity. It is called whenever an Entity changes its
// 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 starts viewing an animation performed by an Entity.
ViewEntityAnimation(e Entity, a EntityAnimation)
// 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 @@ -91,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, EntityAnimation) {}
func (NopViewer) ViewParticle(mgl64.Vec3, Particle) {}
func (NopViewer) ViewSound(mgl64.Vec3, Sound) {}
func (NopViewer) ViewBlockUpdate(cube.Pos, Block, int) {}
Expand Down

0 comments on commit 02fa0e8

Please sign in to comment.