Privacy
Language: Português (Brasil)

Faces in packs and clips

Add looks, eye shapes and reaction changes to a resource pack, and key the face in any clip. Every key, value and range, with full files to copy.

This page has not been translated into Brazilian Portuguese yet, so it is shown in English. Read in English

On this page

A pack can give Punchy! Moves new looks, new drawn eye shapes and a different look for a reaction, and any animation clip can change the face while it plays. This page is for pack makers. You will make a look called cheeky, an eye shape called gem and a reaction that plays the look when you start running in Punchy! Studio, and key the face in a clip in Punchy! Studio or in Blockbench. Then every key and value is listed, with complete files you can copy.

If you only want to change your own settings or your own eyes, read the Faces overview and the Face editor first.

Before you start

  • Install Punchy! Moves from Modrinth or CurseForge (Getting started has the steps) and make a resource pack with a pack.mcmeta. Create an animation shows how.
  • Look at your player in third person. First person draws no face.
  • Use a skin with clear eyes. If the face finds no eyes on your skin, it draws no face on it, and Studio’s Face tab says so. You can mark the eyes by hand in the Face editor, and Studio uses those marks too.
  • Names of looks and eye shapes use lower case letters, digits and underscores. The game lower-cases a name and turns spaces into underscores, and Studio accepts up to 48 characters.

Where the files go

A face has three kinds of parts, and a clip can add a fourth thing on top.

WhatWhere it lives in a packWhat it holds
Looksassets/punchy_moves/faces/looks/<name>.jsonA whole expression: lids, brows, pupils, marks and a shape for each eye.
Eye shapesassets/punchy_moves/faces/shapes/<name>.jsonPixel art for an eye, in one or more colors.
Reaction changesassets/punchy_moves/faces/triggers.jsonWhich look a reaction plays, and how strong the reaction is.
Faces in clipsIn the clips of assets/punchy_moves/animations/*.jsonA look held for the clip, or face channels keyed like any bone.

The name of a look or shape is its file name without .json. Files must sit directly in looks or shapes. A file in a subfolder is not read.

Your own folder works like a pack for looks and shapes: config/punchy_moves/faces/looks and config/punchy_moves/faces/shapes. A reaction change from a player is picked in the face editor’s Test tab instead of a file.

A later layer wins by name. Your own folder wins over the packs, a pack higher in the list wins over a lower one, and all of them win over the built-in looks and shapes. Moves reads every face file when the game starts and again on each resource reload, so press F3+T after a change.

Make a face

Pick the tool you work in. The files these steps write are listed in full in The same pack as files.

Tool

In Punchy! Studio

Punchy! Studio makes every part of a face, shows it on your own skin as Punchy! Moves draws it, and writes the files for you. These steps use a pack with a wave clip, such as the one Your first pack makes in Studio. If you do not have Punchy! Studio yet, get it from Modrinth or CurseForge. The recordings below were made with the example pack provided by Crafto, Fluid & Foolish, installed in the game.

Make the look

  1. In Punchy! Studio, choose Third Person with the switch between the menus and the workspace tabs and open your pack. See Punchy! Studio for making or opening one.
  2. Open the Face tab. On the left is the Faces list with Looks, Eye shapes and Reactions. In the middle is your skin’s face, with the eyes the game found.
  3. Choose File > New Look (Ctrl+N), type the Name cheeky and press Create.
  4. Set Extends to happy. Every part you do not set now comes from Happy.
  5. Set Left lid to 1 for a wink, Blush to 1 and Brow tilt to -0.5. The preview shows each change as Punchy! Moves draws it.
Making the look cheeky: its name, Extends, and the lid, blush and brow tilt fields.

A built-in look offers Change in Pack, which writes the pack’s own version under the same name, and New Look from This.

Draw the eye shape

  1. Choose File > New Eye Shape (Ctrl+Shift+N), type the Name gem and press Create. The shape starts with empty grids for eyes one and two texels tall.
  2. The grid opens at the eye size your skin’s eyes use. The Eye size list marks it as on your skin. Each square of the grid is half a texel.
  3. Set Color to Own color and type #4FC3F7. Paint the outline of a gem on the grid with the pointer. This is color 1.
  4. Under Colors, press + to add color 2. The new color is picked, and the picker below changes it: choose a dark blue. Click a few squares in the middle of the gem.
  5. Press + again for color 3, choose white and paint a glint in one corner.
  6. Click a swatch to paint with that color again. Right-click one for Remove color.
  7. Leave Mirror for the left eye ticked, so both eyes face the same way from the nose.
  8. Select the look cheeky again and set its Right eye to gem. Leave the left eye as it is, winking.
Painting the gem eye shape in three colors.

For every other eye size you want the shape on, pick the size in the menu under Grid size (it reads None, left of Remove size): it adds an empty grid of that size to paint. An eye with no grid of its size takes the nearest one, kept in its middle.

Give a reaction the look

  1. Click Reactions in the Faces list to open it (or type in Search faces), and find Starting a run under Running and crouching.
  2. Set Plays to cheeky. From now on, starting a run makes this face.
  3. To make it outrank or give way to other reactions, tick Own priority and change Priority. Reset Reaction leaves it as the game has it.
The cheeky look's Right eye set to gem, the last step of drawing the eye shape, then Starting a run set to play the cheeky look in the Reactions list.

Key the face in a clip

  1. Open the Animation tab and the wave clip, and put the playhead at 0.3 s.
  2. Go back to the Face tab, select the look cheeky and press Key in Clip (K). The look is keyed in the clip at the playhead, held in full.
  3. In the Animation tab, the outliner’s Face now lists Look: cheeky and Face mix, which Studio keyed with it.
  4. For a blink, select Lids and set its Value to 0 at 0.9 s, 1 at 1.0 s and 0 again at 1.1 s. Without the key at 0.9 s, the lids would stay shut from the start of the clip, because a channel holds its first key’s value before it.
  5. Turn on View > Game View and scrub the clip. Your own player shows the face, with your pack’s look and eye shape, before you export.
Keying the cheeky look and the Lids channel in the wave clip, then the Game view showing the face, gem eye included, on your own player.
Game view plays the wave clip on your own player, Front and Back turning the camera. This recording was made before the face was keyed, so the player shows its usual face.

Export and try it

  1. Press Ctrl+E (File > Export to Resource Pack). In Export Punchy Moves Pack, keep Turn the pack on and reload ticked and press Export.
  2. The pack now has faces/looks/cheeky.json, faces/shapes/gem.json and faces/triggers.json, written as Punchy! Moves reads them, and the face keys are in the clip.
  3. Close the editor with F6 and press F5 twice to see your player from the front. Stand still, press C and pick Wave, the emote Your first pack makes of the clip. Your player waves with the cheeky look and the blink you keyed.
  4. Start a run. For a moment your face is the cheeky look, this time from the reaction.
Exporting the pack, then picking Wave on the emote wheel: the wave plays with the cheeky look, its gem eye and the blink.

Video coming soon

The Game view plays the face keys of a clip, but it does not preview reaction changes. Export, and start a run in third person to see yours.

In Blockbench

Blockbench keys the face in a clip: a look, an eye shape or any face channel, at the playhead, with the face drawn on the rig’s head as you scrub. The look and eye shape files themselves are made in Punchy! Studio or by hand (The same pack as files), and then keyed here. A rig exported from Studio lists your pack’s own looks and eye shapes in the panel. The plain rig lists the built-in ones.

Key a look, an eye shape and a channel

  1. Load punchy_moves_rig.js and open the rig as The Blockbench rig describes. In the Moves Face panel, click Use a skin and pick your skin, a 64 by 64 PNG. The panel says which eyes it found.
  2. Open the Animate tab and select your animation, or add one with the + button.
  3. With the playhead at 0, find Look in the Moves Face panel. Pick happy, leave the number beside it at 1 and press Key. This keys the look and also Face mix at 1 when the clip has none yet.
  4. Move the playhead to 1.0 s, set the number to 0 and press Key. The look lets go.
  5. Select the bone face_shape_arc_left in the eye_shapes folder of the outliner, put the playhead at 1.1 s and add a position key with Y at 0. Without it the wink would show from the start of the clip, because a channel holds its first key’s value before that key.
  6. Move to 1.2 s. Under Eye shapes, pick arc for Left eye and press Key. The head shows a wink. To let the shape go, put the playhead at 1.8 s and add a position key with Y at 0 on the same bone.
  7. Under Channels at the playhead, put the playhead at 0 and press the Key of Pupils with both sliders at 0. Move to 1.8 s, drag the X slider of Pupils to 1 and press its Key. Move to 2.0 s, drag it back to 0 and press Key again.
  8. Press play to check the face. When you are done, choose Animation > Export Animations and save into your pack’s assets/punchy_moves/animations folder.
Adding bow_greeting, keying the head and keying a look in the Moves Face panel.

Video coming soon

The file Blockbench writes holds the face as bones whose names start with face_, in the clip next to the body bones. Faces in clips lists every one.

Animation > Export Animations writes the clip with its face bones.

The same pack as files

This is the same pack as the steps above, written by hand. It holds the look with the face key of the clip, which plays the same as the face_look_cheeky and face_mix keys the steps make. Put it in your resourcepacks folder as my_first_pack, or add the faces folder and the changes to the pack from Getting started.

my_first_pack/
  pack.mcmeta
  assets/
    punchy_moves/
      animations/
        wave.json
      compat/
        emotes.json
      faces/
        looks/
          cheeky.json
        shapes/
          gem.json
        triggers.json

pack.mcmeta, with the resource format of Minecraft 1.21.11. On another version, put that version’s number from the table on Resource packs in place of the 75s:

{
  "pack": {
    "description": "My first Punchy Moves pack",
    "pack_format": 75,
    "min_format": 75,
    "max_format": 75
  }
}

faces/shapes/gem.json, an eye shape in three colors:

{
  "closed": false,
  "color": "#4FC3F7",
  "colors": { "2": "#0D47A1", "3": "#FFFFFF" },
  "on_white": false,
  "mirror": true,
  "grids": {
    "4x2": [".##.", "#23#"],
    "4x4": [".##.", "#22#", "#23#", ".##."]
  }
}

faces/looks/cheeky.json, a look that uses it:

{
  "extends": "happy",
  "lid_left": 1,
  "blush": 1,
  "tilt": -0.5,
  "eyes": ["gem", "open"]
}

faces/triggers.json, which makes starting a run play the look:

{
  "kickoff": "cheeky"
}

animations/wave.json, the wave clip with the look held for its whole length and one blink at 1 second:

{
  "format_version": "1.8.0",
  "animations": {
    "wave": {
      "animation_length": 1.2,
      "loop": true,
      "face": "cheeky",
      "bones": {
        "right_arm": {
          "rotation": {
            "0": [0, 0, 0],
            "0.3": [0, 0, 140],
            "0.6": [0, 0, 110],
            "0.9": [0, 0, 140],
            "1.2": [0, 0, 0]
          }
        },
        "head": {
          "rotation": { "0.3": [0, 0, 8] }
        },
        "face_lids": {
          "position": { "0.0": [0, 0, 0], "0.9": [0, 0, 0], "1.0": [0, 1, 0], "1.1": [0, 0, 0] }
        }
      }
    }
  }
}

compat/emotes.json, which puts the clip on the emote wheel:

{
  "format_version": "2",
  "defaults": { "animations": {} },
  "emotes": {
    "entries": [
      { "id": "wave", "display_name": "Wave", "animation": "wave" }
    ]
  }
}
  1. In the game, open Options, then Resource Packs, move my_first_pack to the right-hand list and press Done. Press F3+T if the game was already running.
  2. Switch to third person with F5. Start a run: the face turns cheeky for a moment, with the left eye winking and the right eye the blue gem.
  3. Stand still and press C to open the emote wheel. Pick Wave. Your player waves with the cheeky face and blinks at 1 second.

Video coming soon

Looks

A look is one JSON file in faces/looks. Every key is optional, and a key you leave out keeps its value from the look you extend, or 0.

Keys of a look
KeyTypeDefaultWhat it doesExample
extendslook namenoneStarts from another look: one in a pack or a built-in one. A look in your own folder can also start from a pack's look, but a pack's look cannot start from one in your own folder. Every part the look does not set comes from it. An unknown name leaves this look out."excited"
lidsnumber, 0 to 10Both top lids, from open (0) to shut (1).
lid_rightnumber, 0 to 10The avatar's right eye shut at least this far. A wink is one lid at 1.1
lid_leftnumber, 0 to 10The avatar's left eye shut at least this far.1
slantnumber, -1 to 10The lids step down toward the nose (positive, a cross look) or away from it (negative, a sad look).0.8
lowernumber, 0 to 10The lower lids rise.
cheeksnumber, 0 to 10The cheeks push the lower lids up, as in a smile. A value above 1 adds nothing.
widenumber, 0 to 10The whites of the eyes grow upward, by up to 1 texel. A value above 1 adds nothing.
pupils[x, y]centerWhere the pupils sit, in texels. x is toward the avatar's left and y is up. Both numbers are needed.[0.5, 0.25]
swingnumber0The pupils swing from side to side on their own. Not clamped.0.3
tremblenumber0The pupils shake. Not clamped, and scaled by 0.25 when drawn.0.4
browsnumber or [right, left]0One number moves both brows, up when positive, in texels. An array is the avatar's right brow and then the left, and it must hold two numbers.[1, 0]
brow_rightnumber0The right brow alone, in texels, up positive.
brow_leftnumber0The left brow alone, in texels, up positive.
tiltnumber, -1 to 10The inner ends of the brows go up (positive, worried) or down (negative, cross).-1
blushnumber, 0 to 10Pink cheeks.
tearsnumber, 0 to 10Tears running from the eyes. Past 0.35 a drop also falls.
sweatnumber, 0 to 10A drop of sweat on the forehead. It shows past 0.35.
bagsnumber, 0 to 10Dark rings under the eyes.
angernumber, 0 to 10The anger vein on the forehead. It shows past 0.35.
sparklenumber, 0 to 10A second glint low in each pupil. It shows past 0.35, and only while the player has Eye sparkle on Line or Dot.
bobnumber0The brows bob to a beat. Not clamped, and scaled by 0.3 when drawn.
eyesshape name or [right, left]openThe shape each eye takes. One name sets both eyes. An array sets the avatar's right eye and then the left, and must hold two names. open is the painted eye and blank is its white alone. A name that is not a known shape leaves the look out.["gem", "open"]
blinknumber, 0 or morenone (the pace of the look it extends, else the usual pace)How often the eyes blink while the look plays. 1 is the usual pace, 0 never blinks and a bigger number blinks more often. A negative number counts as 0.

The right eye is the avatar’s own right, which is the left half of the face on the skin file. Other keys in a look file are ignored, so a misspelled key changes nothing. A look that cannot be read is left out, and the rest of the pack’s looks still load.

Three looks to copy

faces/looks/gleam.json, wide eyes with a glint and slow blinks:

{
  "extends": "happy",
  "wide": 1,
  "pupils": [0.5, 0.25],
  "sparkle": 1,
  "blink": 0.5
}

faces/looks/mismatch.json, a heart in one eye, one brow raised:

{
  "eyes": ["heart", "open"],
  "brows": [1, 0],
  "tilt": 0.5,
  "swing": 0.3
}

faces/looks/grumble.json, a grumpy, tired face:

{
  "extends": "neutral",
  "lids": 0.3,
  "slant": 0.8,
  "lower": 0.4,
  "bags": 1,
  "tilt": -1,
  "anger": 1,
  "tremble": 0.4,
  "blink": 0.6
}

The looks that come with Moves

There are 40, in the editor’s order: neutral, happy, joyful, excited, sparkly, love, proud, smug, relaxed, zen, wink, sly, sneaky, curious, focused, squint, determined, furious, menacing, strain, surprised, shocked, scared, nervous, worried, sad, crying, pain, wince, dizzy, knocked, sick, tired, sleepy, bored, cold, hot, blinded, wary and shut.

These short names also work anywhere you type a look: cross, calm, flutter, narrow, wink_left, wink_right, startled, glum, uneasy, cheery, intent, aghast, hurting, drowsy, laugh, angry, glance_left and glance_right.

A look in your pack with a built-in name replaces the built-in look wherever a reaction plays it unchanged. Save a happy.json and the reactions that play Happy as it is play yours. A reaction that adjusts Happy, such as looking toward something or blinking at a changed pace, keeps the built-in one.

Eye shapes

An eye shape is pixel art that replaces an eye while a look or a clip asks for it. It is one JSON file in faces/shapes, with one drawing for each eye size.

Moves has nine shapes of its own: open (the eye as the skin paints it), line (shut, a single line), arc (a smile’s arch), cup (a cup), press (squeezed shut, shown as > <), cross (an x), spiral, heart and blank (the eye’s white alone). line, arc, cup, press and cross are closed shapes. A pack or a player can redraw any of them under its own name, except open and blank, and every look that uses the shape then draws the new one.

Keys of an eye shape
KeyTypeDefaultWhat it doesExample
gridsRequiredobjectOne drawing per eye size, in half texels. Each key is <columns>x<rows>, both from 1 to 16, and each value is a list of row texts. The number of rows and the width of every row must match the key, or the shape is left out.{ "4x2": [".##.", "#23#"] }
color"line" or #RRGGBBlineWhat # paints, called color 1. line is the eye's line color, so the shape follows every skin and the player's Line color of closed eyes. A hex color, with or without #, is fixed. Text that is not a hex color leaves the shape out."#4FC3F7"
colorsobjectnoneUp to eight more colors, named by the digit the grids paint them with, from "2" to "9". Each is a hex color. A digit with no color here paints nothing.{ "2": "#0D47A1", "3": "#FFFFFF" }
closedbooleanfalseThe eye is closed in this shape, so blinks pass it by: no blink lid is drawn over it, and a change between two closed shapes skips the quick blink.
on_whitebooleanfalseThe box under the drawing is the eye's white instead of the lid's skin.
mirrorbooleantrueThe avatar's left eye shows the drawing mirrored, so both eyes face the same way from the nose. An eye in the middle is never flipped.

Grids

A grid is a picture of the eye’s box. Each square is half a texel of the skin. The key says how many squares wide and tall: 4x2 is an eye two texels wide and one tall, 4x4 is two by two, and 4x3 is two wide and one and a half tall. Studio marks the size your skin’s eyes use in its Eye size list.

Give a grid for every size you want the shape on. An eye with no grid of its size takes the nearest grid, kept in its middle.

The box is filled with the lid’s skin (or the eye’s white, with on_white), and the squares you paint go over it. Each character of a row is one square:

CharacterWhat it paints
.Nothing. The box shows through.
#The shape’s own color, color 1 from color.
X, x, 1, o, O, *The same as #.
2 to 9The color of that digit from colors. A digit with no color paints nothing.
Any other characterNothing.

Colors 2 to 9

Color 1 is the color key. Colors 2 to 9 are the colors object, so a shape can use nine colors in all. Write each as exactly six hex digits, with or without #, such as #FFD447. A three digit color is read with zeros in front (#FD4 becomes 000FD4, a dark blue). A color of more than six digits is not read as red, green, blue and alpha: depending on its digits it either leaves the shape out or is read as its last six digits.

This shape, faces/shapes/rainbow.json, uses all eight extra colors, one for each digit:

{
  "closed": false,
  "color": "line",
  "colors": {
    "2": "#FF4D4D",
    "3": "#FF9F43",
    "4": "#FFD447",
    "5": "#A6F2B8",
    "6": "#5FF2E0",
    "7": "#4FC3F7",
    "8": "#CFB2FF",
    "9": "#FFA8D2"
  },
  "mirror": true,
  "grids": {
    "4x2": ["2345", "6789"],
    "4x4": ["2345", "2345", "6789", "6789"]
  }
}

Redraw a built-in shape

Save a shape under a built-in name and Moves draws yours instead, everywhere the shape plays. This faces/shapes/arc.json redraws the smile’s arch with your own pixels. It is a closed shape, and its line follows each skin’s line color:

{
  "closed": true,
  "color": "line",
  "grids": {
    "4x2": [".##.", "#..#"],
    "4x4": ["....", ".##.", "#..#", "#..#"]
  }
}

A shape drawn on the white, faces/shapes/ring.json, a dark ring on the eye’s white:

{
  "closed": false,
  "color": "#2A2A2A",
  "on_white": true,
  "grids": {
    "4x4": [".##.", "#..#", "#..#", ".##."]
  }
}

Reaction changes

faces/triggers.json changes what a reaction plays. Each key is a reaction’s id, and the full list with each id and priority is on Face reactions. The value is a look name, or an object with look and priority.

Keys of a reaction change
KeyTypeDefaultWhat it doesExample
<reaction id>Requiredstring or objectA look name, or an object with the keys below. The id is the one in Face reactions."kickoff": "cheeky"
looklook namethe reaction's own lookThe look the reaction plays when it applies. A name that is not found keeps the reaction's own look."cheeky"
prioritywhole numberthe reaction's own priorityHow strong the reaction is. The strongest reaction that applies sets the whole look, so a bigger number wins.900

This file is valid as it stands:

{
  "kickoff": "cheeky",
  "munch": { "look": "gleam" },
  "shear": { "look": "cheeky", "priority": 900 },
  "sneak": { "priority": 500 }
}

Starting a run (kickoff) plays cheeky. Eating (munch) plays gleam at its own priority. Shearing (shear) plays cheeky at 900, which is above Eating at 850, where it was 785. Sneaking (sneak) keeps its look and rises from 385 to 500.

Every pack’s triggers.json counts. When two packs change the same reaction, the higher pack wins, and its entry replaces the lower one whole, priority included. The player’s own pick in the face editor’s Test tab wins over a pack’s change, and the player’s reaction switches still turn reactions on and off.

Faces in clips

Any clip can carry a face, in two ways that mix: hold a look for the whole clip, or key face channels like any other bone. Face keys are read from the clips in a pack’s animations folders.

Hold a look

The face key of a clip takes a look’s name, or an object with look and mix.

The face key of a clip
KeyTypeDefaultWhat it doesExample
facelook name or objectnoneA look held for the whole clip. A name is trimmed, lower-cased and its spaces become underscores. A blank name does nothing."sleepy"
face.lookstringThe look's name. It must be text."proud"
face.mixnumber, 0 to 11How much of the face the clip takes over from the reactions. 1 is all of it, so the face is only the look.0.8
{
  "format_version": "1.8.0",
  "animations": {
    "wake_up": {
      "animation_length": 2.5,
      "face": "sleepy",
      "bones": {
        "head": { "rotation": { "0.0": [12, 0, 0], "2.5": [0, 0, 0] } }
      }
    },
    "proud_pose": {
      "animation_length": 2.0,
      "face": { "look": "proud", "mix": 0.8 },
      "bones": {
        "head": { "rotation": { "0.0": [0, 0, 0], "1.0": [-6, 0, 0], "2.0": [0, 0, 0] } }
      }
    }
  }
}

This is a shorthand for two face bones held for the whole clip: face_mix at mix and face_look_<name> at 1. A face bone that the clip keys itself replaces the shorthand’s.

Key face channels

The face is a set of bones named face_... in the same clip, keyed like any other bone. You need no cubes. Moves reads each bone’s position and uses its Y value, and the pupils use X as well. Rotation and scale of a face bone are not read. A bone you do not key stays at 0 and leaves the face alone.

A face key takes lerp_mode and easing like any other key. To use them, write the key as an object, as in the last example below. A key written as an array is always linear. The values are the face’s own units, shares of an eye and texels on the skin, not model pixels, so the same keys work on every skin.

A bone held for the whole clip can be written as one array, inside the clip’s bones object:

{
  "bones": {
    "face_mix": { "position": [0, 1, 0] }
  }
}

Or keyed over time, with the time in seconds as the key:

{
  "bones": {
    "face_cheeks": {
      "position": { "0.0": [0, 0, 0], "0.3": [0, 1, 0], "1.0": [0, 1, 0], "1.3": [0, 0, 0] }
    }
  }
}

To ease into a key, write that key as an object with post for the value and easing for the curve (the curves are listed in Animation files). The easing shapes the move that ends on that key:

{
  "bones": {
    "face_cheeks": {
      "position": {
        "0.0": [0, 0, 0],
        "0.3": { "post": [0, 1, 0], "easing": "easeInOutSine" },
        "1.0": [0, 1, 0],
        "1.3": [0, 0, 0]
      }
    }
  }
}
Face bones in a clip
KeyTypeDefaultWhat it doesExample
face_mixposition Y, 0 to 10How much of the face the clip takes over from the reactions. At 0 your keys add to the reactions' face. At 1 the face is only what the clip keys.
face_look_<name>position Y, 0 to 10How much of a look the clip holds. The name is a look of your own folder, of a pack, or a built-in look or short name. Key two looks to cross fade between them. Weights add up when two bones name the same look, and a look that does not exist is skipped.face_look_happy
face_shape_<name>_right, face_shape_<name>_leftposition Y0That eye takes the shape while the value is above 0.5. The strongest shape wins. A shape bone with no side sets both eyes. A shape that does not exist is skipped.face_shape_arc_left
face_lidsposition Y, 0 to 10Both top lids, added on top of the looks.
face_lid_right, face_lid_leftposition Y, 0 to 10One eye shut at least this far.
face_slantposition Y, -1 to 10Lid slant, as the look key.
face_lower, face_cheeks, face_wideposition Y, 0 to 10Lower lids, cheeks and wide eyes, as the look keys. Cheeks and wide stop at 1.
face_tiltposition Y, -1 to 10Brow tilt, as the look key.
face_pupilsposition X and Y, in texels0, 0The pupils. Positive X is toward the avatar's left and positive Y is up.[1, 0, 0]
face_browsposition Y, in texels0Both brows, up when positive, down when negative.
face_brow_right, face_brow_leftposition Y, in texels0One brow.
face_swing, face_tremble, face_bobposition Y0Pupil sway, tremble and brow bob, as the look keys.
face_blush, face_tears, face_sweat, face_bags, face_anger, face_sparkleposition Y, 0 to 10The marks, as the look keys.
face_blink_offposition Y0Above 0.5, the face's own blinks stop. Use it for a clip that keys every blink itself.

How a clip’s face adds up

Each frame, every part of the face is the reactions’ look, less the share that face_mix takes over, plus each held look by its weight, plus the keyed parts. In numbers: part = (1 minus mix) times the reactions’ value, plus the keyed value. Say the reactions show blush 0.5, and a clip keys face_mix at 0.5 and face_blush at 0.5. The blush is 0.5 times 0.5, plus 0.5, which is 0.75. With face_mix at 1 it would be just 0.5. For the parts that have a range, the sum is clamped when the face is drawn, so a blush of 1.4 shows as 1.

With no face_mix, keyed parts simply add to whatever face the reactions show, such as an extra blink or a raised brow.

Each eye shows the strongest shape the clip keys past 0.5. If it keys none, then while face_mix is past 0.5 the eye takes the shape of the strongest held look, and otherwise the shape the reactions show. While face_mix is past 0.5 the face blinks at the pace of the strongest held look, the usual pace if that look sets none.

A clip’s face shows over every reaction up to a long fall and a hard landing. Only a swelling creeper, a warden, the hurt startle, sleeping and dying show over it. The face eases in and out with the clip.

Clips to copy

cheer holds Happy for a second, winks with a smile, then looks cross. Each channel’s first key holds a value of 0 on purpose (in cheer, face_look_happy starts at 1 to hold Happy from the first frame): a channel holds its first key’s value before that key, so nothing shows until the move starts.

{
  "format_version": "1.8.0",
  "animations": {
    "cheer": {
      "animation_length": 3.0,
      "bones": {
        "face_mix": { "position": { "0.0": [0, 0, 0], "0.2": [0, 1, 0], "2.7": [0, 1, 0], "3.0": [0, 0, 0] } },
        "face_look_happy": { "position": { "0.0": [0, 1, 0], "1.0": [0, 1, 0], "1.2": [0, 0, 0] } },
        "face_shape_arc_left": { "position": { "1.2": [0, 0, 0], "1.25": [0, 1, 0], "1.8": [0, 1, 0], "1.85": [0, 0, 0] } },
        "face_cheeks": { "position": { "1.2": [0, 0, 0], "1.3": [0, 1, 0], "1.8": [0, 1, 0], "1.9": [0, 0, 0] } },
        "face_brows": { "position": { "1.9": [0, 0, 0], "2.2": [0, -0.75, 0], "2.7": [0, 0, 0] } },
        "face_tilt": { "position": { "1.9": [0, 0, 0], "2.2": [0, -1, 0], "2.7": [0, 0, 0] } },
        "face_anger": { "position": { "2.0": [0, 0, 0], "2.1": [0, 1, 0], "2.5": [0, 1, 0], "2.6": [0, 0, 0] } }
      }
    }
  }
}

look_around has no face_mix, so its keys add to the face the reactions show. The pupils glance left, then right, and the brows rise at the first glance:

{
  "format_version": "1.8.0",
  "animations": {
    "look_around": {
      "animation_length": 3.0,
      "bones": {
        "head": { "rotation": { "0.0": [0, 0, 0], "1.0": [0, 20, 0], "2.0": [0, -20, 0], "3.0": [0, 0, 0] } },
        "face_pupils": { "position": { "0.0": [0, 0, 0], "1.0": [1, 0, 0], "2.0": [-1, 0, 0], "3.0": [0, 0, 0] } },
        "face_brows": { "position": { "0.0": [0, 0, 0], "1.0": [0, 0.5, 0], "1.5": [0, 0, 0] } }
      }
    }
  }
}

slow_blinks stops the face’s own blinks and keys two blinks itself:

{
  "format_version": "1.8.0",
  "animations": {
    "slow_blinks": {
      "animation_length": 3.0,
      "bones": {
        "face_blink_off": { "position": [0, 1, 0] },
        "face_lids": {
          "position": {
            "0.0": [0, 0, 0],
            "0.8": [0, 0, 0],
            "1.2": [0, 1, 0],
            "1.6": [0, 0, 0],
            "2.2": [0, 0, 0],
            "2.6": [0, 1, 0],
            "3.0": [0, 0, 0]
          }
        }
      }
    }
  }
}

mood_swing cross fades from Sad to Happy, then turns both eyes into hearts. It uses face_mix at 1, so the face is only what the clip keys:

{
  "format_version": "1.8.0",
  "animations": {
    "mood_swing": {
      "animation_length": 3.0,
      "bones": {
        "face_mix": { "position": [0, 1, 0] },
        "face_look_sad": { "position": { "0.0": [0, 1, 0], "1.0": [0, 1, 0], "1.5": [0, 0, 0] } },
        "face_look_happy": { "position": { "0.0": [0, 0, 0], "1.0": [0, 0, 0], "1.5": [0, 1, 0], "3.0": [0, 1, 0] } },
        "face_shape_heart": { "position": { "2.0": [0, 0, 0], "2.05": [0, 1, 0], "2.6": [0, 1, 0], "2.65": [0, 0, 0] } }
      }
    }
  }
}

A clip only plays when a compat file points to it, for example as an emote. See Compat files and Animation files.

Emotes and looks

An emote can name a look that plays with it: "face": "happy", or "expression". An emote with no face plays Happy.

The name is matched exactly as typed, in lower case, against the built-in looks and their short names, such as wink_left and wink_right. A capital letter, a space or a look that only your pack defines plays Happy. If your pack redraws a built-in look under its name, your version plays, except for the short names wink_right, flutter, glance_left and glance_right, which always play the built-in drawing.

To play a look that is new in your pack with an emote, name it in the emote’s clip with face, as wave does above. Only your own player’s emotes carry a face. See Keys and emotes and Compat files.

{
  "format_version": "2",
  "emotes": {
    "entries": [
      { "id": "wink", "display_name": "Wink", "animation": "wink_clip", "face": "wink_left" },
      { "id": "doze", "display_name": "Doze", "animation": "wake_up", "face": "sleepy" }
    ]
  }
}

The first entry needs a clip named wink_clip in your animations, and the second uses the wake_up clip from above. An emote whose clip is not loaded does not reach the wheel.

Values and ranges

Units are the face’s own. A share is 0 to 1 of the way, and a texel is one pixel of the skin’s face.

PartKeysRange and unit
Lidslids, lid_right, lid_left0 to 1, open to shut.
Lid slantslant-1 to 1. Positive steps down toward the nose, negative away from it.
Lower lidslower0 to 1.
Cheekscheeks0 to 1. Above 1 adds nothing.
Wide eyeswide0 to 1, in texels. Above 1 adds nothing.
Pupilspupils, face_pupilsTexels. X is toward the avatar’s left, Y is up. The Blockbench panel’s sliders run from -2 to 2.
Browsbrows, brow_right, brow_left, face_browsTexels, up positive. A negative value lowers the brow.
Brow tilttilt-1 to 1. Positive raises the inner ends (worried), negative lowers them (cross).
Pupil sway, tremble, bobswing, tremble, bobNot clamped. Tremble is scaled by 0.25 and bob by 0.3 when drawn. 1 is a full effect.
Marksblush, tears, sweat, bags, anger, sparkle0 to 1. sweat, anger and the glint from sparkle show past 0.35, and tears add a falling drop past 0.35.
Blink paceblink0 or more. 1 is usual, 0 never.
Clip mixface.mix, face_mix0 to 1.
Look weightface_look_<name>0 to 1.
Shapes and no blinksface_shape_<name>_right, face_shape_<name>_left, face_blink_offActive above 0.5.
Reaction prioritypriorityA whole number. The biggest one that applies wins.

Lids, lower lids, cheeks, wide eyes, lid slant, brow tilt and the marks act as the nearest end of their range when the face is drawn, so a stray 1.4 on a lid is a closed lid. Pupil sway, tremble and bob are not clamped. Pupils and brows take any number, but the drawing stops them: a pupil is drawn only inside its eye, and toward the outer corner it can slide 0.3 texel further than its room, narrowing against the edge. A brow stops at the top of the face and never drops over more than half of its eye.

Things that go wrong

A file is left out

  • A look is missing. It was left out because extends names an unknown look, eyes names an unknown shape or has fewer than two names in an array, pupils or brows has too few numbers, or a value is not a number. The other looks still load.
  • An eye shape is missing. It has no grids, a grid whose rows do not match its key, a size outside 1 to 16, or a color or colors value that is not a hex color. A shape named open or blank is refused, because those two cannot be redrawn.
  • None of a file’s reaction changes work. A triggers.json that does not parse, or that has an entry whose priority is not a number or whose look is an object, is skipped whole. An entry whose value is a list or null is skipped on its own.
  • The rest of an animation file is lost. A clip’s face object whose look is an object, an empty list or a list of several items stops that clip and the rest of its file. The clips before it stay. Write look as text in quotes.
  • A file is in a subfolder. Looks and shapes are read only directly in faces/looks and faces/shapes.

Unreadable looks, eye shapes and triggers.json files in a pack are named in the game’s log, in messages that start with Face:. Search logs/latest.log for Face:. Files in your own folder are named only when the game starts. Press F3+T after a fix.

A clip file that stops this way is not named in the log, so check that the face of each clip is text, or an object whose look is text.

To see one for yourself, copy faces/looks/grumble.json from Three looks to copy into my_first_pack/assets/punchy_moves/faces/looks/, next to cheeky.json. In the copy, delete the last line, the closing }. Press F3+T, then search logs/latest.log for Face:. The line names punchy_moves:faces/looks/grumble.json and says why it could not be read. Each line in the log starts with a time and the thread, so read the whole line. Put the brace back and press F3+T again to load the look.

Video coming soon

Nothing shows

  • The face does not change. A reaction id that is not in the reaction list, or spelled differently, changes nothing. A look name in triggers.json that no look has keeps the reaction’s own look.
  • A clip’s face is hidden. A creeper about to blow, a warden, a hit, sleeping and dying show over a clip’s face.
  • A clip’s look mixes with the reactions’ face. Without face_mix a held look adds to what the reactions show. Key face_mix at 1 with the look, or use face, which does it for you.
  • The lids stay shut. A channel holds its first key’s value before that key. Key the channel at 0 at the start of the clip, then key the move.
  • A misspelled channel does nothing. A bone named face_cheek instead of face_cheeks is kept and changes nothing on the face. In a clip with no animation_length, its keys still count toward the clip’s length.
  • An emote shows Happy. The emote’s face only knows built-in look names, in lower case. Name your own look in the clip with face.
  • No face at all. First person draws none, and a skin the face finds no eyes on has none. See the Face editor.

Colors go wrong

  • A color comes out dark. It has three digits, which are read with leading zeros. Write six, such as #FFD447.
  • A color has the wrong hue. It has eight digits starting with 0 to 7, and only the last six are read. Write six.
  • A shape disappears. A color that is not hex, an eight digit color starting with 8 to F (such as #FF4FC3F7, with the alpha first), a longer color too large to read, or a missing grids leaves the shape out.
  • A digit in a grid paints nothing. The shape’s colors has no color for that digit.

Last checked against the mod on 30 October 2026.