Content
Emotes
An emote is an animation played on a player, wearing their own skin. They disappear for its length, a rig of them dances in their place, and they are put back exactly where they were.
/emote wave
/emote handshake Steve
/emote stopTab completion offers every emote the server holds, and once you have typed one that needs a partner it offers the players who could be it — and stops offering once the last slot is filled.
The rig is not the animation#
Two separate things, and mixing them up makes nothing about emotes make sense.
The rig is a model of that player, cut out of their skin. It is generated, never authored: nobody opens Blockbench to make a rig for Steve.
The animation is keyframes — a wave, a bow, a handshake — and is authored once, for everybody. It moves bones by name, so the same wave fits every player alive.
That split is also why an emote needs a push. A resource pack is built and downloaded before anybody moves, and it cannot reach out to a live skin, so the pack has to carry a baked rig for each player it was built for. A player absent from that pack has no rig in it and cannot emote — which the command says out loud, rather than putting a Steve in their place.
Somebody joined after the push
That is the whole of it, and the fix is one more push. Emotes.canPerform is
the same question in Java.
The engine bakes its own rigs too, from the skins of everybody who joins, so a
server with no Studio pack at all still has them. A player it has never seen
has nothing in the pack yet, which is why a brand-new arrival appears as the
default rig for a moment — riding a vehicle or sitting in a seat is usually
where somebody first notices it. It rebuilds and re-sends at once, and
anybody who arrives during that rebuild is covered by a single follow-up
rather than costing one each; emotes.bake-on-join: false in
config.yml turns that off for a server that would rather
pick its own moment, and /rp reload bakes whatever has arrived since.
Getting emotes onto a server#
Make them in Studio, then push:
- 1
Sync
In Studio, open your pack and hit Sync. It shows a pairing code. In game:
/rp sync <code>. - 2
Push
Hit push in Studio. The pack arrives, the emotes with it, and the rigs are baked for whoever is on that sync.
- 3
Emote
/emoteand tab, and everything in the pack is there.
/rp emotes lists what the server is holding right now.
Models inside an emote#
An emote can carry a pack model as a prop. If only part of that model moves, Studio stores the motion as an ordinary animation on the model and names it in the emote manifest. RP Engine then renders the model as its normal multi-part rig and seeks it to the emote's playhead on every emote step. The player's bones and the model therefore share one clock: a lifted barbell stays in the lifter's hands instead of moving the whole bench or playing on an unrelated loop.
Sharing a push#
A sync is one player's, so a second person testing the same pack would need a second code. Instead, put them on yours:
/rp sync add Steve they get /rp sync accept, or deny
/rp sync who who is on it
/rp sync remove Steve and the pack comes back off them
/rp sync leave if you are on somebody else's
/rp sync stop end yours, for everybodyIt exists to answer "who else receives my pushes", so it lives as long as the sync does — there is nothing to disband and no ownership to hand on.
Emotes with a cast#
Some emotes take more than one person: a handshake, a hug, a high five. The lead names the others and everybody is teleported into position, turned to face correctly, and given their positions back at the end.
Nobody is moved until every participant and every destination has been checked, and the emote ends for everybody or for nobody.
An invited player is asked first — /emotereply accept or deny — so nobody is
dragged across the room by a stranger. That command is deliberately ungated: a
player who cannot reply is a player who cannot refuse.
rpengine.emote.cast is who may name a cast at all. rpengine.emote.force
skips the invitation, for staff running an event.
Movement sets#
A movement set is a group of emotes you wear rather than perform once — a walk, a run, an idle, applied for as long as you have it on. Wearing one is the same command:
/emote strutGroups and single emotes share one list of names and one name space, so nothing can collide and nothing has to be told apart to be typed.
Walk cycles follow the player, not the clock#
A walk is not a thing that happens over a second — it happens over a stride. So the walk, sprint and crouch-walk members of a set are played by how far the player travelled, not by how long they took: standing still, the legs stop; on soul sand they slow down; under a speed potion or a raised walk-speed attribute they keep up. The feet stay on the ground either way.
Author each cycle for Minecraft's ordinary pace and it plays exactly as you drew it, because that is the speed the engine divides by:
| State | Author it for |
|---|---|
| Walk | 4.317 blocks per second |
| Sprint | 5.612 blocks per second |
| Crouch-walk | 1.295 blocks per second |
Standing still, crouching in place and being off the ground are not gaits — an idle breathes at its own rate and a jump is on gravity's clock — so those three play at the rate they were drawn at, whatever the player is doing.
Changing pace does not restart anything. The engine joins the new cycle at the point nearest the pose already on screen, so breaking into a run picks the run up mid-stride on the same leg, and eases between the two cycles rather than cutting.
What stops an emote#
Being hit. Moving, in most cases. /emote stop. A plugin cancelling
EmoteStartEvent, or calling Emotes.stop. When it ends, whatever invisibility
the player already had comes back — minus the time the emote took, so an emote
cannot be used to extend a potion.
Hand-authored emotes#
Emote animations are authored in Studio today and arrive by push. There is no
emotes/ folder in the content format — deliberately, because a folder that
loaded and then did nothing would be an afternoon's work with no error to
explain it. When keyframes can be hand-written, that folder appears, and
nothing about the commands or the API changes.