这是基岩版1.12.0的MoLang文档。
版本:1.12.0.28
为什么要创造Molang?
MoLang是一种简单的基于表达式的语言,为实时且快速地计算数值而设计。它的设计重点是在JavaScript无法大规模执行的需要更高性能的系统中启用类似脚本的功能。我们需要这些底层系统中的脚本功能来支持用户修改模组,自定义实体,渲染和动画。
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 its 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 to 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(query.anim_time); return temp.foo * temp.foo; variable read-write values, usually related to the current entity variable.my_saved_var = variable.my_saved_var + 1; query read-only values, usually related to current entity query.is_baby geometry current render controller "geometry": "array.geos[query.is_sheared]" material current render controller "materials": [ { "*": "material.default" }, { "leg*": "material.legs" } ] texture current render controller "textures": ["array.skins[query.is_saddled]"]
Keywords
All identifiers not in a scope listed below are reserved for future use
- Parameters
Keyword Description "float" "Numerical constant value" "( )" "Circle Brackets / Parentheses for expression term evaluation control" "[ ]" "Square Brackets for array access" "query.function_name" "Access to an entity's properties" "math.function_name" "Various math functions (see below)" "temp.variable_name" "Store an intermediate value for the duration of the current expression" "variable.variable_name" "Store a value on the attached entity for later use" "geometry.texture_name" "A reference to a texture named in the entity definition" "material.texture_name" "A reference to a texture named in the entity definition" "texture.texture_name" "A reference to a texture named in the entity definition" "! && || < <= >= > == !=" "Logical operators" "* / + -" "Basic math operators" "test ? if true : if false" "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(value)" "Absolute value of value" "math.sin(value)" "Sine (in degrees) of value" "math.cos(value)" "Cosine (in degrees) of value" "math.exp(value)" "Calculates e to the value'th power" "math.ln(value)" "Natural logarithm of value" "math.pow(base, exponent)" "Elevates base to the exponent'th power" "math.sqrt(value)" "Square root of value" "math.random(low, high)" "Random value between low and high inclusive" "math.ceil(value)" "Round value up to nearest integral number" "math.round(value)" "Round value to nearest integral number" "math.trunc(value)" "Round value towards zero" "math.floor(value)" "Round value down to nearest integral number" "math.mod(value, denominator)" "Return the remainder of value / denominator" "math.min(A, B)" "Return lowest value of A or B" "math.max(A, B)" "Return highest value of A or B" "math.clamp(value, min, max)" "Clamp value to between min and max inclusive" "math.lerp(start, end, 0_to_1)" "Lerp from start to end via 0_to_1" "math.lerprotate(start, end, 0_to_1)" "Lerp the shortest direction around a circle from start degrees to end degrees via 0_to_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 v.s. Complex Expressions
A simple expression is a single statement, the value of which is returned to the system that evaluated the expression. e.g.:
math.sin(query.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(query.anim_time * 1.23); temp.my_other_temp_var = Math.cos(query.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(query.modified_distance_moved * 38.17) * query.modified_move_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.variable_name" and "query.function_name" 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.
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 materials (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 be 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[query.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(query.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 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, it 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 expressions. Useful 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" ]
实体查询清单
名称 注释 query.all_animations_finished 仅在动画控制器中有效。如果当前动画控制器状态下的所有动画至少播放了一次,则返回1.0,否则返回0.0。 query.anim_time 返回自当前动画开始以来的时间(以秒为单位),如果未在动画中调用则返回0.0 query.any_animation_finished 仅在动画控制器中有效。如果当前动画控制器状态中的任何动画至少播放了一次,则返回1.0,否则返回0.0。 query.armor_color_slot 将护甲栏编号作为参数,并返回请求的护甲栏中护甲的颜色 query.armor_material_slot 将护甲栏编号作为参数,并返回请求的护甲栏中护甲的类型 query.armor_texture_slot 将护甲栏编号作为参数,并返回请求的护甲栏中护甲的纹理类型 query.blocking Returns 1.0 if the entity is blocking, else it returns 0.0 query.body_y_rotation Returns the body yaw rotation if called on an actor, else it returns 0.0 query.can_climb 如果实体可以爬升,则返回1.0,否则返回0.0 query.can_fly 如果实体可以飞行,则返回1.0,否则返回0.0 query.can_power_jump Returns 1.0 if the entity can power jump, else it returns 0.0 query.can_swim 如果实体可以游泳则返回1.0,否则返回0.0 query.can_walk 如果实体可以行走,则返回1.0,否则返回0.0 query.current_squish_value Returns the squish value for the current entity, or 0.0 if this doesn't make sense query.delta_time 返回自上一帧以来的时间(以秒为单位) query.frame_alpha Returns the ratio (from 0 to 1) of how much between AI ticks this frame is being rendered query.ground_speed 返回实体的地面速度,以米/秒为单位 query.has_armor_slot 将护甲栏编号作为参数,如果实体在请求的护甲栏中有护甲,则返回1.0,否则返回0.0 query.has_collision 如果实体有碰撞检测,则返回1.0,否则返回0.0 query.has_gravity 如果实体受重力影响,则返回1.0,否则返回0.0 query.has_owner 如果实体有所有者ID,则返回true,否则返回false query.has_rider Returns 1.0 if the entity has a rider, else it returns 0.0 query.has_target 如果实体有它的目标,则返回1.0,否则返回0.0 query.head_roll_angle 返回狼头部的侧倾角 query.head_x_rotation Takes one argument as a parameter. Returns the nth head x rotation of the entity if it makes sense, else it returns 0.0 query.head_y_rotation Takes one argument as a parameter. Returns the nth head y rotation of the entity if it makes sense, else it returns 0.0 query.invulnerable_ticks 如果可行,则返回该实体剩余的无敌刻,否则返回0.0 query.is_angry 如果实体生气,则返回1.0,否则返回0.0 query.is_avoiding_mobs 如果实体正在逃离某实体,则返回1.0,否则返回0.0 query.is_baby 如果实体是幼儿,则返回1.0,否则返回0.0 query.is_breathing 如果实体正在呼吸,则返回1.0,否则返回0.0 query.is_bribed Returns 1.0 if the entity has been bribed, else it returns 0.0 query.is_carrying_block 如果实体携带方块,则返回1.0,否则返回0.0 query.is_casting Returns 1.0 if the entity is casting, else it returns 0.0 query.is_charged Returns 1.0 if the entity is charged, else it returns 0.0 query.is_charging Returns 1.0 if the entity is charging, else it returns 0.0 query.is_chested 如果实体附有箱子,则返回1.0,否则返回0.0 query.is_critical Returns 1.0 if the entity is critical, else it returns 0.0 query.is_dancing 如果实体在跳舞,则返回1.0,否则返回0.0 query.is_delayed_attacking returns 1.0 if the entity is attacking using the delayed attack, else it returns 0.0 query.is_eating 如果实体正在食用食物,则返回1.0,否则返回0.0 query.is_elder 如果实体是成年的,则返回1.0,否则返回0.0 query.is_enchanted 如果实体已附魔,则返回1.0,否则返回0.0 query.is_fire_immune 如果实体免疫火焰伤害,则返回1.0,否则返回0.0 query.is_first_person Returns 1.0 if the entity is being rendered in first person mode, else it returns 0.0 query.is_gliding 如果实体滑动,则返回1.0,否则返回0.0 query.is_grazing 如果实体在放牧,则返回1.0;否则,则返回0.0 query.is_idling 如果实体闲置,则返回1.0,否则返回0.0 query.is_ignited 如果实体被点燃,则返回1.0,否则返回0.0 query.is_illager_captain 如果实体是袭击队长,则返回1.0,否则返回0.0 query.is_in_love 如果实体恋爱了,则返回1.0,否则返回0.0 query.is_in_water 如果实体在水中,则返回1.0,否则返回0.0 query.is_in_water_or_rain 如果实体在水或雨中,则返回1.0,否则返回0.0 query.is_interested 如果实体感兴趣,则返回1.0,否则返回0.0 query.is_invisible 如果实体已隐身,则返回1.0,否则返回0.0 query.is_jumping 如果实体在跳跃,则返回1.0,否则返回0.0 query.is_laying_down 如果实体躺下,则返回1.0,否则返回0.0 query.is_laying_egg 如果实体正在下蛋,则返回1.0,否则返回0.0 query.is_leashed 如果实体被拴住,则返回1.0,否则返回0.0 query.is_lingering Returns 1.0 if the entity is lingering, else it returns 0.0 query.is_moving 如果实体正在移动,则返回1.0,否则返回0.0 query.is_on_ground 如果实体在地面上,则返回1.0,否则返回0.0 query.is_onfire 如果实体着火,则返回1.0,否则返回0.0 query.is_orphaned Returns 1.0 if the entity is orphaned, else it returns 0.0 query.is_powered 如果实体已充能(如苦力怕),则返回1.0,否则返回0.0 query.is_pregnant 如果实体已怀孕,则返回1.0,否则返回0.0 query.is_resting 如果实体处于静止状态,则返回1.0,否则返回0.0 query.is_riding 如果实体在骑行,则返回1.0,否则返回0.0 query.is_roaring 如果实体当前正在咆哮,则返回1.0,否则返回0.0 query.is_rolling 如果实体正在滚动,则返回1.0,否则返回0.0 query.is_saddled 如果实体有鞍,则返回1.0,否则返回0.0 query.is_scared 如果该实体害怕,则返回1.0,否则返回0.0 query.is_shaking 如果实体正在发抖,则返回1.0,否则返回0.0 query.is_shaking_wetness 如果实体正在甩水,则返回true query.is_sheared 如果实体能够被剪切并被剪切,则返回1.0,否则返回0.0 query.is_shield_powered 如果该实体有处于防御状态的盾,则返回1.0,否则返回0.0 query.is_silent Returns 1.0 if the entity is silent, else it returns 0.0 query.is_sitting 如果实体坐着,则返回1.0,否则返回0.0 query.is_sleeping 如果实体正在睡眠,则返回1.0,否则返回0.0 query.is_sneaking 如果实体正在潜行,则返回1.0,否则返回0.0 query.is_sneezing 如果实体在打喷嚏,则返回1.0,否则返回0.0 query.is_sprinting 如果实体正在冲刺,则返回1.0,否则返回0.0 query.is_stackable 如果实体是可堆叠的,则返回1.0,否则返回0.0 query.is_standing 如果实体站立则返回1.0,否则返回0.0 query.is_stunned 如果该实体当前处于眩晕状态,则返回1.0,否则返回0.0 query.is_swimming 如果实体正在游泳,则返回1.0,否则返回0.0 query.is_tamed 如果已驯服实体,则返回1.0,否则返回0.0 query.is_transforming 如果实体正在变身,则返回1.0,否则返回0.0 query.is_using_item 如果实体正在使用物品,则返回1.0,否则返回0.0 query.is_wall_climbing 如果实体正在爬墙,则返回1.0,否则返回0.0 query.item_in_use_duration Returns the amount of time an item has been in use in seconds up to the maximum duration, else 0.0 if it doesn't make sense query.item_max_use_duration 返回该物品可以使用的最长时间,否则返回0.0。 query.item_remaining_use_duration 返回该物品可以使用的剩余时间(以秒为单位),否则返回0.0。 query.key_frame_lerp_time 返回上一个和下一个关键帧之间的比值 query.lie_amount 返回实体的躺下次数 query.life_span 返回实体的总存活时间,如果实体永久存在,则返回0.0 query.life_time 返回自当前动画开始以来的时间(以秒为单位),否则返回0.0(如果未在动画中调用) query.log debug log a value query.mark_variant Returns the entity's mark variant query.max_trade_tier 如果有意义,则返回实体的最大交易阶段,否则返回0.0 query.model_scale 返回当前实体的比例 query.modified_distance_moved 返回实体在水平方向上移动的总米数(自从上次加载以来,不一定是最初创建实体以来) 该状态由状态标记(例如is_baby或on_fire)修改
query.modified_move_speed 返回由状态标志(例如is_baby或on_fire)修改的实体的当前行走速度 query.overlay_alpha 请勿使用——此功能已弃用,将被删除 query.previous_squish_value 返回当前实体的前一个压缩值,如果没有意义,则返回0.0 query.roll_counter 返回实体的滚动计数 query.shake_angle 返回狼实体的摇动角度 query.sit_amount 返回实体的坐下计数 query.skin_id 返回实体的皮肤ID query.sneeze_counter 返回实体的打喷嚏计数 query.spellcolor.r query.spellcolor.g
query.spellcolor.b
如果可行,则返回当前实体拼写颜色的红/绿/蓝色通道,否则返回0.0 query.standing_scale Returns the scale of how standing up the entity is query.swell_amount Returns how swollen the entity is query.swelling_dir Returns the swelling direction of the entity if it makes sense, else it returns 0.0 query.tail_angle 返回狼实体尾巴的角度,否则返回0.0 query.target_x_rotation 如果有意义,则返回瞄准实体当前指向所需转动的x轴角度,否则返回0.0 query.target_y_rotation 如果有意义,则返回瞄准实体当前指向所需转动的y轴角度,否则返回0.0 query.time_stamp Returns the current time stamp of the level query.trade_experience 如果有意义,则返回该实体的当前交易经验,否则返回0.0 query.trade_tier 如果有意义,则返回实体的贸易阶段,否则返回0.0 query.unhappy_counter 返回实体的不满意程度 query.variant Returns the entity's variant index query.wing_flap_position Returns the wing flap position of the entity, or 0.0 if this doesn't make sense query.wing_flap_speed Returns the wing flap speed of the entity, or 0.0 if this doesn't make sense query.yaw_speed 返回实体转向的程度数字