Values
Values are the backbone of all runtime logic. Values are just scoreboard objectives under the hood, but their representation in MCCompiled is much different. There are a couple of key differences about values:
Values act identical to variables in other programming languages.
Regular math operations:
a + b
Compound assignment:
a += b
Declaration:
define int a
Values can have types.
Values have no length restrictions on names.
Values are formatted when displayed to a player.
Defining Values
Defining a value is done using the syntax define [type] [name]
. The most common type is int
, short for integer. An integer can be any whole number between -2,147,483,648 and 2,147,483,647. It's versatile, and is the closest to a Minecraft scoreboard objective.
Assigning Values
To assign something to a value, use the assignment =
symbol. By default, the assignment always happens to the executing entity, @s
. If you want to change which entity gets the value assigned, see clarification.
Values can be assigned to other values as well; notice that the difference between scoreboard operation
and scoreboard set
is abstracted away entirely.
Merging Define and Assignment (and type omission)
If you wish to combine an assignment and a definition into one line, you can do that! Specify the assignment just after the define command is completed. When merging definition/assignment, you can omit the type if you want, as it will be inferred from the value you're assigning.
The following two examples have identical behavior. Note that in the second example, the type int
is omitted because the compiler can tell what type 'number' should be based on the input 21
.
Initializing Values
If you're familiar with scoreboard objectives in Minecraft, you may know that score-holders may not have any score at all. Not zero, but nothing at all. You can use the init
command to initialize a value so that if a score-holder doesn't hold it, the value will be set to the default (usually 0).
Simple Math
All the math operations in MCCompiled are listed here:
- No Compound Assignment
Adds the left and right values.
define a = 10 define b = 4 define result result = a + b assert result == 14Subtracts the right value from the left value.
define a = 10 define b = 4 define result result = a - b assert result == 6Multiplies the left and right values.
define a = 10 define b = 4 define result result = a * b assert result == 40Divides the left value by the right value.
define a = 10 define b = 4 define result result = a / b assert result == 2Divides the left value by the right value, but returns the remainder.
define a = 10 define b = 4 define result result = a % b assert result == 2
Compound Assignment
When you need the left value to store the result of the operation, you can use what is called compound assignment. Compound assignment is specified by using an equals-sign =
after the operator you wish to use.
- With Compound Assignment
Adds the right value to the left value.
define a = 10 define b = 4 a += b assert a == 14Subtracts the right value from the left value.
define a = 10 define b = 4 a -= b assert a == 6Multiplies the left value with the right value.
define a = 10 define b = 4 a *= b assert a == 40Divides the left value by the right value.
define a = 10 define b = 4 a /= b assert a == 2Divides the left value by the right value, but sets the left value to the remainder.
define a = 10 define b = 4 a %= b assert a == 2
Complex Statements
MCCompiled fully supports the use of operations inline, as well as PEMDAS ordering. Using inline operations keeps code size way down and communicates its purpose much more clearly than separating operations per-line.
The order that MCCompiled evaluates complex statements mostly conforms to PEMDAS along with some extra steps added for the other features in the language:
Evaluate everything inside parentheses recursively.
()
[]
Run any dereferences.
$
Run function calls.
name(...)
Apply any indexers.
[...]
Evaluate multiplication/division operations.
a * b
Evaluate addition/subtraction operations.
a - b
The following example shows the use of a complex statement to calculate the amount of score remaining until a player reaches the next level of a theoretical game:
Clarification
By default, values point to @s
, or the executing entity. This default works for a majority of cases; however, when you need to change who the value points to, clarifiers are the answer.
A clarifier is defined as a selector encased in square brackets (indexers). For example, a clarifier pointing to all cows would look like [@e[type=cow]]
, and one pointing to the nearest non-self player would look like [@p[rm=0.1]]
.
The following example shows adding one to losses
for all players with the tag 'touched'
Other ways of doing the above example
Miscellaneous Operations
Some operations don't follow the rules of the five main math operations, those of which are listed here. None of the operations listed here are mentioned as assignment or not, they just exist as-is.
- Miscellaneous Operations
Swaps the left and right values.
define a = true define b = false a >< b assert a == false assert b == true
Attributes
Attributes can change the way values behave. Any number of attributes can be applied pretty much anywhere in the definition; before or after the type. See attributes for all attributes across the language.
- global
Makes the attached value global, meaning that the value's scoreboard objectives are always tied to the global fakeplayer
_
.Any attempts to use clarifiers on the value will result in a compile-time error. The value is guaranteed to never be attached to an entity.
Examples & Use-case
Making values global is useful for anything that applies to the world, and not a specific player/entity. If you were designing a mini-game, for example, you would want the game-related code to be global, along with the compile-time guarantees that it will remain global.
define global int playersPassed define global time timeRemaining function display { globalprint "PASSED: {playersPassed} | TIME LEFT: {timeRemaining}" }- bind
Binds the value to a given MoLang query. Requires one parameter, being a string that contains the query to use. The current list of supported bindings is here.
Most bindings come with pre-defined entities they attach to, but in cases where they don't, the entities can be manually specified by adding more string parameters to the end of the function, i.e.,
bind("query.is_sleeping", "fox")
to bind specifically to foxes.Examples & Use-case
Binding replaces all cases where animation controllers were needed to access extra information about entities.
define bool bind("query.is_sleeping") isSleeping if not isSleeping { summon lightning_bolt print @a "{@s} IS RUINING THE SMP!!!" }