动画系统(重制版)


Animation for Remake Version

This section is the documentation of the animation scripting system.

Custom Animation

The mod uses JavaScript as animation scripting language. The reason for choosing it is that nashorn JavaScript engine is built-in in Java 8. It is efficient, and also more capable of complex calculations comparing to expressions.

This tutorial will not talk about learning JavaScript. You can find various learning resources on the Internet.

The script file must be named animation.js and be put in the same directory as main JSON file. There are 3 functions to be implemented in the animation script file:

function init(entity, model) {}
function update(entity, model) {}
function tick(entity, model) {}

The first function will only be invoked once when the model is applied on an entity. The second function will be invoked every frame, while the third function will be invoked every game tick.

You can access some properties of the entity or the model through the two parameters. For example, you can create a blink animation by several lines of JavaScript:

var blink;

function init(entity, model) {
    blink = model.getBone("blink");
}

function tick(entity, model) {
    blink.setVisible(entity.getAge() % 60 < 5);
}

This script makes the bone blink to be visible for 5 game ticks per 3 seconds. It is recommended to get all referenced bone instances in init function, and access them in tick or update. This can reduce computation consumption. A comprehensive documentation of the entity and model interface is in the next section.

Physics Animation

By default, bones will move along with their parents like rigid bodies. With physics feature, you can let some bones to move "softly", like scarfs or hairs. This is done by physicalizing bones in the init function:

function init(entity, model) {
    model.getBone("scarf_left_1").physicalize(0, 5, 0.5, 0, 0);
    model.getBone("scarf_left_2").physicalize(0, 5, 0.8, 0, 0);
    model.getBone("scarf_left_3").physicalize(0, 5, 0.8, 0, 0);

    model.getBone("scarf_right_1").physicalize(0, 5, 0.5, 0, 0);
    model.getBone("scarf_right_2").physicalize(0, 5, 0.8, 0, 0);
    model.getBone("scarf_right_3").physicalize(0, 5, 0.8, 0, 0);
}

Note that once a bone is physicalized, it cannot be undone. The physicalize function takes 5 parameters:

  • elasticity: ≥ 0, strength of the force applied when parent bone moves, pointing to movement direction.
  • stiffness: ≥ 0, strength of the force applied constantly to recover the initial direction relative to the parent bone.
  • damping: ≥ 0, < 1, multiplies to the velocity of current bone every game tick to simulate damping.
  • friction: ≥ 0, strength of the force applied in the opposite direction of the velocity of player entity.
  • gravity: strength of the gravity (or buoyancy for negative values).

When making physics animations, be sure that the +Z axis (the blue axis in BlockBench) of the physicalized bone is pointed to the bone's desired direction:

physics

physics

Scripting Documentation

All functions except those in the Model interface that have return values will not return undefined or null. When the required item / effect does not exist, an empty instance will be returned. You can invoke isEmpty() on them to check if they are empty or not.

The Entity Interface

function getLimbSwing(): number    // deprecated
function getAnimPosition(): number
// Get animation position.

function getLimbSwingAmount(): number    // deprecated
function getAnimSpeed(): number
// Get animation speed.

function getAge(): number
// Get ticks count since entity spawn.

function getHeadYaw(): number
// Get entity head yaw.

function getHeadPitch(): number
// Get entity head pitch.

function getPartial(): number
// Get the render progress from last tick to current tick [0 - 1).

function getScale(): number
// Get the current scale (The one that can be adjusted in CPM Gui).

function getHealth(): number
// Get entity health.

function getMaxHealth(): number
// Get entity maximum health.

function getFoodLevel(): number
// Get entity food level (If not player, return 0).

function getSaturationLevel(): number
// Get entity saturation level (If not player, return 0).

function getHurtTime(): number
// Get remaining time for entity to render red. If not hurt, return 0.

function getPosX(): number
function getPosY(): number
function getPosZ(): number
// Get entity position.

function getMotionX(): number
function getMotionY(): number
function getMotionZ(): number
// Get entity motion.

function getBodyYaw(): number
// Get entity body yaw.

function getSwingProgress(): number
// Get swing item progress.

function getPose(): string
// Get entity pose. This returns the pose defined by Minecraft, all possible values are:
// standing
// crouching (or sneaking in previous versions)
// sleeping
// swimming (also for crawling when moving in 1 block height spaces)
// elytra_flying
// trident_attacking
// dying

function isAlive(): boolean
// Is entity alive.

function isBurning(): boolean
// Is entity on fire.

function isGlowing(): boolean
// Is entity glowing.

function isHurt(): boolean
// Is entity hurt (same with getHurtTime() > 0).

function isInLava(): boolean
// Is entity in lava.

function isInWater(): boolean
// Is entity in water.

function isInvisible(): boolean
// Is entity invisible.

function isOnGround(): boolean
// Is entity on ground.

function isRiding(): boolean
// Is current entity riding another entity.

function isSneaking(): boolean    // deprecated
function isCrouching(): boolean
// Is entity crouching.

function isSprinting(): boolean
// Is entity sprinting.

function isWet(): boolean
// Is entity in water or in rain.

function isCustomKeyDown(index: number): boolean
// Is custom keys pressed by player. There are 16 custom keys currently. Index start from 0.

function getMainHandItem(): ItemStack
// Get item in main hand.

function getOffHandItem(): ItemStack
// Get item in off hand.

function getRightHandItem(): ItemStack
// Get item in right hand.

function getLeftHandItem(): ItemStack
// Get item in left hand.

function getHelmetItem(): ItemStack
// Get helmet item.

function getChestplateItem(): ItemStack
// Get chestplate item.

function getLeggingsItem(): ItemStack
// Get leggings item.

function getBootsItem(): ItemStack
// Get boots item.

function getInventoryItem(index: number): ItemStack
// Get inventory item. Index ranges from 0 to 35. 0 - 8 means hotbar.

function getPotionEffect(effectName: string): PotionEffect
// Get current potion effect. Effect names are the same with their resource locations.

The Model Interface

function getBone(name: string): Bone
// Get the bone with given name.

function getTexture(partName: string): string
// Get texture used by given model part.

function setTexture(partName: string, textureName: string): void
// Set texture of given model part.

function getParticle(particleName: string): Particle
// Get the particle instance with given name.

function getItemModel(itemName: string): ItemModel
// Get the item model instance with given name.

function isFirstPerson(): boolean
// Is rendering first person.

The Bone Interface

function getParent(): Bone
// Get parent bone.

function getPositionX(): number
function getPositionY(): number
function getPositionZ(): number
// Get bone position.

function getRotationX(): number
function getRotationY(): number
function getRotationZ(): number
// Get bone rotation.

function getScaleX(): number
function getScaleY(): number
function getScaleZ(): number
// Get bone scale.

function getColorR(): number
function getColorG(): number
function getColorB(): number
function getColorA(): number
// Get bone color.

function isVisible(): boolean
// Is bone invisible.

function setPositionX(value: number): void
function setPositionY(value: number): void
function setPositionZ(value: number): void
function setPosition(x: number, y: number, z: number): void
// Set bone position.

function setRotationX(value: number): void
function setRotationY(value: number): void
function setRotationZ(value: number): void
function setRotation(x: number, y: number, z: number): void
// Set bone rotation.

function setScaleX(value: number): void
function setScaleY(value: number): void
function setScaleZ(value: number): void
function setScale(x: number, y: number, z: number): void
function setScale(value: number): void
// Set bone scale.

function setColorR(value: number): void
function setColorG(value: number): void
function setColorB(value: number): void
function setColorA(value: number): void
function setColor(r: number, g: number, b: number, a: number): void
// Set bone color.

function setVisible(value: boolean): void
// Set bone visibility

function physicalize(elasticity: number, stiffness: number, damping: number,
                     friction: number, gravity: number): void
// Apply physics effects on this bone. See the last chapter of Modeling section for reference.

The Particle Interface

function getTexture(): string
// Get used texture.

function setTexture(texture: string): void
// Set texture.

function getBone(): Bone
// Get attached bone.

// Below are the getters and setters of all particle properties.
function getPositionRangeX(): number
function getPositionRangeY(): number
function getPositionRangeZ(): number
function getDirectionRange(): number
function getMinAngle(): number
function getMaxAngle(): number
function getMinSpeed(): number
function getMaxSpeed(): number
function getMinRotationSpeed(): number
function getMaxRotationSpeed(): number
function getMinLifeSpan(): number
function getMaxLifeSpan(): number
function getDensity(): number
function getMinColorR(): number
function getMaxColorR(): number
function getMinColorG(): number
function getMaxColorG(): number
function getMinColorB(): number
function getMaxColorB(): number
function getMinColorA(): number
function getMaxColorA(): number
function getMinSize(): number
function getMaxSize(): number
function getGravity(): number

function isCollide(): boolean

function setPositionRangeX(value: number): void
function setPositionRangeY(value: number): void
function setPositionRangeZ(value: number): void
function setDirectionRange(value: number): void
function setMinAngle(value: number): void
function setMaxAngle(value: number): void
function setMinSpeed(value: number): void
function setMaxSpeed(value: number): void
function setMinRotationSpeed(value: number): void
function setMaxRotationSpeed(value: number): void
function setMinLifeSpan(value: number): void
function setMaxLifeSpan(value: number): void
function setDensity(value: number): void
function setMinColorR(value: number): void
function setMaxColorR(value: number): void
function setMinColorG(value: number): void
function setMaxColorG(value: number): void
function setMinColorB(value: number): void
function setMaxColorB(value: number): void
function setMinColorA(value: number): void
function setMaxColorA(value: number): void
function setMinSize(value: number): void
function setMaxSize(value: number): void
function setGravity(value: number): void

function setCollide(value: boolean): void

The Item Model Interface

function getBone(): Bone
// Get attached bone.

function getItem(): string
// Get item id.

function setItem(itemId: string): void
// Set item id.

function isEnchanted(): boolean
// Is item enchanted.

function setEnchanted(value: boolean): void
// Set item enchanted.

The Item Stack Interface

function isEmpty(): boolean
// Is empty.

function getItem(): string
// Get item id.

function getCount(): number
// Get item count.

The Potion Effect Interface

function isEmpty(): boolean
// Is empty.

function getAmplifier(): number
// Get effect amplifier.

function getDuration(): number
// Get effect duration.