MOLANG DOCUMENTATION
Version: 1.9.0.10

Index

Why Does MoLang Exist?

MoLang is a simple expression-based language designed for fast calculation of values at run-time. Its focus is solely to enable script-like capabilities in high-performance systems where JavaScript is not performant at scale. We need scripting capabilities in these low-level systems to support end-user modding capabilities, custom entities, rendering, and animation.

Lexical Structure

The language structure is largely based on simple C-style syntax, focusing on handling math expressions. A script is made of either one expression for simple cases, or can be made of several where intermediate values are required or to help reduce compute time.

In all cases, the value of the last expression in a script provides the script's value. In a multi-expression script, all but the last expression must assign a value to a variable. The last expression can as well, but doesn't need to as it's value is assumed to be the used as the return value.

Values

-Value types are concretely specified, or numeric if not.
-All numerical values are floats.
-Boolean values such as actor flags are converted to a float value of either 0.0 or 1.0 for values of false or true respectively.
-For boolean tests, a float value equivalent to 0.0 is false, and anything not equal to 0.0 is true.
-For array indices, floats are c-style cast to ints, and clamped at zero for negative values or wrapped by the array size for large values.
-Other supported types are textures, materials, and geometry where they make sense (such as render controllers).
-Errors generally return a value of 0.0.

Variables

There are several domains a variable may belong to:

Parameters

Domain Scope Example
Temp Current expression Temp.foo = Math.sin(global.anim_time);
return Temp.foo * Temp.foo;
geometry Current render controller "geometry": "array.geos[query.is_sheared]"
material Current render controller "materials": [ { "*": "material.default" }, { "leg*": "material.legs" } ]
query Read-only values, usually related to current entity query.is_baby
texture Current render controller "textures": ["array.skins[query.is_saddled]"]
variable Current entity variable.my_saved_var = variable.my_saved_var + 1;

Keywords

All identifiers not in a scope listed below are reserved for future use

Parameters

Keyword Description
Numerical constant value
( ) Parentheses for expression term evaluation control
Brackets for array access
query. Access to an entity's properties
math. Various math functions (see below)
global. Access to environment parameters
temp. Store an intermediate value for the duration of the current expression
variable. Store a value on the attached entity for later use
geometry. A reference to a texture named in the entity definition
material. A reference to a texture named in the entity definition
texture. A reference to a texture named in the entity definition
! && || < <= >= > == != Logical operators
* / + - Basic math operators
? : Conditional operator
this The current value before executing the script (context sensitive)
return For complex expressions, this evaluates the following statement and stops execution of the script, returns the value computed

Math Functions

Parameters

Function Description
math.abs() Absolute value of
math.sin() Sine (in degrees) of
math.cos() Cosine (in degrees) of
math.exp() Elevates Euler to the 'd power
math.ln() Natural logarithm of
math.pow(, ) Elevates to the 'd power
math.sqrt() Square root of
math.random(, ) Random value between and inclusive
math.ceil() Round up to nearest integral number
math.round() Round to nearest integral number
math.trunc() Round towards zero
math.floor() Round down to nearest integral number
math.mod(, ) Return the remainder of value / denominator
math.min(, ) Return lowest value of or
math.max(, ) Return highest value of or
math.clamp(, , ) Clamp to between and inclusive
math.lerp(, , <0_to_1>) Lerp from to via <0_to_1>
math.lerprotate(, , <0_to_1>) Lerp the shortest direction around a circle from degrees to degrees via <0_to_1>

Global Parameters

Parameters

Name Description
global.anim_time Time since the current animation start
global.delta_time Time since the last time this animation was updated
global.key_frame_lerp_time Normalized time between current key frames as[0 - 1]
global.life_time Lifetime of the current entity
global.frame_alpha The render frame interpolation amount between AI frames(assuming the rendering is running at a different rate than the AI) as[0 - 1]

Types, Values, and Variables

In general, all expression values are floats. In render controllers, some expressions result in a texture or material depending on the context. All array index expressions are processed as floats, and cast to integers when performing the final lookup into the array.Positive array indices wrap by the size of the array.Negative array indices clamp to 0.

Simple vs Complex Expressions

A simple expression is a single statement, the value of which is returned to the system that evaluated the expression. eg:

math.sin(global.anim_time * 1.23)


A complex expression is one with multiple statements, each ending in a ';'. Each statement is evaluated in order. In the current implementation, the last statement requires the use of the return keyword and defines the resulting value of the expression.eg:

temp.my_temp_var = Math.sin(global.anim_time * 1.23);
temp.my_other_temp_var = Math.cos(global.life_time + 2.0);
return temp.my_temp_var * temp.my_temp_var + temp.my_other_temp_var;


Note that in a simple expression, ';' is not allowed, whereas in a complex expression, each statement requires a ';' including the last.





Domain Examples

Entity Definition Scripts

In the definition file there is a section for pre-computing values. These are executed immediately before animation and render controllers are processed, and stored in the entity. The purpose is to pre-compute any expensive and complex values you may want to reuse in your scripts, long-living index variable updates, or generally any one-off computation per render tick.

"scripts": {
    "pre_animation": [
     "variable.my_constant = (Math.cos(global.anim_pos * 38.17) * global.anim_speed;",
      "variable.my_constant2 = Math.exp(1.5);",
    ]
  },


Animation and Animation Controller Files

These are always numerical operations to control which animations are playing and how to animate bones. "variable." and "query." refers to the entity currently being rendered.They have access to everything in the language except material, texture, and geometry types.

Render Controllers

There are a few different kinds of expressions here, where context implies what is allowed. As with animations, the entity accessors refer to the current entity, however depending on the context one also has access to materials, textures, and geometries.There are two sections in a render controller:
-Array definitions (optional)
-Resource usage (required)
The array definition section allows you to create arrays of resources by resource type if you so desire.These can then be referenced in the resource usage section.

Parameters


{
	"controller.render.<my render controller name>": {
  // array definitions
  "arrays": {
   "materials": {
    "Array.<array name>": ["Material.<material name>", "Array.<array name>, ...],
    ...
   },
   "textures" : {
    "Array.<array name>": ["Texture.<texture name>", "Array.<array name>", ...],
    ...
   },
   "geometries" : {
    "Array.<array name>": ["Geometry.<geometry name>", "Array.<array name>", ...],
    ...
   }
  },
  // resource usage
  "geometry": "<geometry expression>",
  "materials" : [
   { <string regex>: "<material expression>" },
   ...
  ],
  "textures" : [
   "Array.<array name>[<numerical expression>]",
    ...
  ]
 }
}


Array Expressions

For each of the three resource types (materials, textures, and geometry), you can define an array of resources. The name of the resource is the nice-name from the definition file. Using materials as an example:

  "arrays": {
      "materials": {
      "array.my_array_1": ["material.a", "material.b", "material.c"],
       "array.my_array_2" : ["material.d", "material.e"],
       "array.my_array_3" : ["array.my_array_1", "material.my_array_2"],
       "array.my_array_4" : ["array.my_array_2", "material.my_array_3"],
       "array.my_array_5" : ["array.my_array_1", "material.my_array_1", "material.my_array_4"],
       "array.my_array_6" : ["array.my_array_1", "material.f"],
       ...
     }, 


Note that all elements of an array must be of the same type. eg: a texture array must only contain textures.

An array can reference any combination of zero or more arrays (including duplicates if desired) and/or zero or more materails (again, including duplicates if you like), and you can have as many arrays as you like, each with as many elements as you like.If an array includes arrays in its members, they do not need to be the same length.When indexing into an array in the resource usage section, you use numerical expressions.If the resulting number is negative, it will use zero as the index.Any non - negative index will converted to an integer, and will wrap based on the size of the array:

index = max(0, <expression_result>) % <array_size>




Resource Expression

A resource expression must return a single resource of a specific type depending on the context.
For example, in the "geometry" section, you must produce an expression that will result in a single geometry. Some examples:
Always use a specific geometry
"geometry": "geometry.my_geo"

Cycle through an array of geometries at a rate of one per second
"geometry": "array.my_geometries[global.anim_time]"

Pick a geo based on an entity flag
"geometry": "query.is_sheared ? geometry.sheared : geometry.woolly"

Use specific geo when sleeping, otherwise flip through an array based on a cosine curve, using index zero for almost half the time while the cosine curve is negative
"geometry": "query.is_sleeping ? geometry.my_sleeping_geo : array.my_geos[math.cos(global.anim_time * 12.3 + 41.9) * 10 + 0.6]"


Resource Sections

Geometry

The geometry section specifies which geometry to use when rendering. As you can specify as many render controllers as you like in the definition file, a single render controller is only concerned with how to render a single geometry.Note that a geometry can be arbitrarily complex using any number of bones and polygons.

Materials

The materials section specifies how to map what material to what bone of the geometry. A single material is mapped to a whole bone. Material expressions are evaluated in the order listed. The first part of each statement is the name of the model part to apply the material to, and the second part is the material to use. The model part name can use * for wild - card matching of characters.For example :

  "materials": [
      { "*": "Material.default" },
      { "TailA": "array.hair_colors[variable.hair_color]" },
      { "Mane": "array.hair_colors[variable.hair_color]" },
      { "*Saddle*": "variable.is_leather_saddle ? material.leather_saddle : material.iron_saddle" }
    ],


-This will start by applying Material.default to all model parts.
-Next, it will set the material on a model part named "TailA" to the result of the expression "Array.hairColors[variable.hair_color]". This will look up some previously created variable on the entity named hair_color and use that to index into a material array called "array.hair_colors" defined in this render controller. This will overwrite the Material.default material set in the line above.
-Third, it will look up the same material as the expression is identical, and apply it to the "Mane" model part.
-Lastly, if will find any model part starting with, ending with, or containing "Saddle" (case sensitive) and change its material to either material.leather_saddle or material.iron_saddle depending on the previously set entity variable variable.is_leather_saddle.









Query Functions

Query Functions are boolean expressions that allow you to query for values owned by the engine under different circumstances. They can be used in MoLang expressionsUseful for controlling things like changing positions, textures, animations, etc if a mob is a baby. For example:

"position": [ 0.0, "query.is_baby ? -8.0 : 0.0", "query.is_baby ? 4.0 : 0.0" ]


List of Entity Flags

Name Description
query.can_climb Mob is able to climb
query.can_damage_nearby_mobs Set by the player's spin attack using the Trident
query.can_fall_through_scaffolding Set when the player is able to fall through scaffolding, for example when flying or descending in scaffolding
query.can_fly Mob is able fly
query.can_power_jump Mob can power jump(added with the minecraft : can_power_jump component
query.can_rider_pick This is set by the "rider_can_interact" Parameter of the minecraft : rideable component.
query.can_show_name This flag is set is the entity can show a name tag
query.can_swim Mob is able to swim
query.can_walk Mob is able to walk
query.ground_speed Entity speed in meters
query.is_angry Mob is currently angry(i.e.wolves that been hit, zombie pigman once hit).Added via the minecraft : angry component
query.is_baby Mob is a baby
query.is_breathing if false, HUD bubbles render(water only)
query.is_bribed Added when the mob is bribed(added through the minecraft : bribable component
query.is_casting Mob is casting a spell. (i.e.Evoker animation of arms in air and to have particles play next to its hands)
query.is_charged This is set on a mob by the charge_charged_trigger parameter on the minecraft : behavior.ranged_attack component(i.e.the blaze's fireball attack)
query.is_charging Mob is using a charge attack(i.e.the vex's charge attack)
query.is_chested If the Mob has a chest on them(i.e.Horses and Donkey chests)
query.is_critical When a critical attach is achieved(i.e.when the player firs a fully charged bow or gets a critical melee attach this causes the particles to play
query.is_dancing When a mob is dancing(i.e.used by parrots to indicate they should dance)
query.is_eating If the mob is eating(i.e.When horses are fed hay or pandas eating)
query.is_elder If the Mob is an elder version(only used on Elder Guardian)
query.is_fire_immune If the mob has minecraft : fire_immune component or the fire resistance potion applied
query.is_gliding Player is gliding(using elytra)
query.is_idling Used when the Agent is idling
query.is_ignited If a mob is ignited.Added through the is_ignited and explode components
query.is_in_love Mob is in its "Love" state by being fed it's tempt item
query.is_in_scaffolding Managed by the minecraft : scaffolding_climber component for when a mob is in scaffolding
query.is_in_transition_sitting If the mob is currently transitioning from sitting or standing(i.e.Pandas when randomly sitting or snacking)
query.is_in_water Is entity in water
query.is_interested Mob is attracted to food the player is holding food they like(added via the minecraft : behavior.beg.) (i.e.tamed wolf sits and turn its head)
query.is_invisible Mob is invisible / affected by Invisibility potion effect
query.is_laying_down Managed by the minecraft : behavior.lay_down goal(i.e.lazy pandas)
query.is_laying_egg If the turtle is laying an egg
query.is_leashed Mob currently has a leash on it.
query.is_lingering Used on potions that are thrown to know it creates a lingering effect.
query.is_moving Mob is currently swimming through water
query.is_onfire Mob is on fire
query.is_orphaned Pets that have lost their owners.
query.is_over_scaffolding Managed by the minecraft : scaffolding_climber component for when a mob is over scaffolding
query.is_powered If mob is charged(i.e.Creeper's blue shield). Added via minecraft:charged component
query.is_pregnant Set by some turtle behavior goals.Used to make pregnant turtles render larger
query.is_resting Pet sleeping with its owner or boat is resting
query.is_riding Player / Mob is riding another Mob
query.is_rolling Set by the minecraft : behavior.roll goal(i.e.baby or playful pandas)
query.is_saddled Mob has a saddle on its back(i.e.pigs and horses)
query.is_scared Managed by the minecraft : behavior.scared goal for when the mob is scared(i.e.scared pandas)
query.is_shaking When Mobs shake off water(i.e.Wolves shaking off water when wet from swimming / rain
query.is_sheared Mob has been sheared.Set with the minecraft : sheared component
query.is_sitting Mob is currently sitting(i.e.dogs and cats)
query.is_sneaking Mob is Sneaking(i.e.players and ocelots)
query.is_sneezing Set by the minecraft : behavior.sneeze goal when the mob is sneezing
query.is_sprinting Mob is Sprinting
query.is_stackable Used on minecarts and boats so that they don't collide through each other. Set via minecraft:stackable component
query.is_standing Mob is stomping(i.e.zombie's minecraft:behavior.stomp_turtle_egg, or Horses and the player jumping )
query.is_swimming True if the Mob is currently swimming
query.is_tamed If Mob is currently tamed(i.e.Dogs use this to draw their collars)
query.is_tempted Mob is tempted by a food item
query.is_transforming This flag is set by the minecraft : transformation component(i.e.Zombie villagers when they are transforming back to villagers)
query.is_using_item Mob is using an item(i.e.players eating food, or players and witches using potions)
query.is_wall_climbing Mob is currently climbing a wall(i.e.spiders)
query.is_wasd_controlled When the mob is being controller by a player riding it



This website is not affiliated with Mojang Studios or Microsoft