Skip to content

documentation

amandin edited this page Aug 15, 2024 · 7 revisions

getting started

installation

NOTE: melon is still in early development stage and not ready to be installed.

in order to install melon you need to have go installed, once you have that just run

go install https://github.com/melonlang/melon

initializing project

after you have installed melon run this command to initialize your project.

melon init

running this command will

syntax

functions

load function

when just writing commands outside any function those will go to the load function.

time set day

other functions

these commands will go to the load function in your namespace (test:load). to create your own function use the func keyword. call it tick to make it run every game-tick

// test:make_day
func make_day() {
  time set day
}

// this is the tick function.
func tick() {
  execute as @a run effect give @s speed 1 100 true
}

functions under directories

to create function under a specific directory, like test:foo/bar we could use one of the following methods

  1. dots in filename, affects the single defined function
func foo.bar() {
  time set day
}
  1. dir block, affects code within the block
dir foo {
  func bar() {
    time set day
  }
}
  1. dir keyword, affects code below the keyword
dir foo

func bar() {
  time set day
}

macro function

macro functions in melon are a little different than in vanilla. you do not have to type $ at the beginning of the line, just use your macro straight up anywhere you want with $(macro_name), but you also have to define the names of your macros in the function's arguments.

func foo(x, y, z) {
  tp @s $(x) $(y) $(z)
}

foo(64, 64, 64) // tps the executor of the command to 64 64 64

blocks

a block is like an anonymous function, can be assigned to a variable, or just used in code in order to use macros.

here's how you assign it to a variable. at first glance it may look like a regular function, but it will prove to be useful when creating your own librarires

// assign to a variable
var foo block = () {
  say "bar"
}

foo() // this outputs "bar"

and here are other ways you could create and use blocks without assigning it to a variable. instead, the block will just execute immediately.

var foo comp = {
  foo: "bar"
  bar: "baz"
}

func find_value_by_key() {
  var input str = @s::SelectedItem.tag.pages[0]

  block (input) {
    print(foo.$(input))
  }
}

func tick() {
  execute as @a[tag=foo] at @s run block () {
    say "for quick, simple tasks without dedicated functions."
  }
}

function decorators

decorators are used to modify functions' behaviour. .... todo: this

variables

nbt operation syntax

melon has a special syntax for nbt operations which is easier to read and faster to type. nbt element consist of two parts separated by ::, first you type the source of the nbt, and then enter path of your nbt element. if you just type an nbt element it will compile to data get command.

nbt::foo.bar
// data get storage nbt foo.bar

[0, 0, 0]::foo.bar
// data get block 0 0 0 foo.bar

@s::foo.bar
// data get entity @s foo.bar

if you want to specify scale in data get use <element> * <scale>

nbt::foo.bar * 0.001

operations

now, to operate nbt use <nbt> <operator> <nbt>. here's an example for each of the operators

// assign
nbt::foo = nbt::bar

// append
nbt::foo << nbt::bar

// prepend
nbt::foo >> nbt::bar

// insert
nbt::foo[5] ^= "inserted at index 5"

// merge
nbt::foo += {text:"bar"}

// <operation> string
nbt::foo = nbt::bar[0:1]

store result / success

you can also store result or success of a command in an nbt element.

// store result
nbt::foo.bar = random 1..5 // return random number from 1 to 5

// store success
nbt::foo.bar ?= random 1..5 // return 1 on success, 0 otherwise

to specify data type or scale when storing use <nbt>(<type>) * <scale> = <command.both scale and type are not required, if not specified default values are going to be used. type set to integer and scale set to 1.

nbt::foo.bar(float) * 1000 = random 1..5

run-time variables

stored as regular values in datapacks. melon data types pretty much copy those of minecraft nbt format with few exceptions:

  • arr can represent byte, int, or long arrays, as well as a list, all in one.
  • int is stored via scoreboard in a fake player.
  • ints special type, an nbt stored integer.
all of the available types in melon
type keyword type name storage method
byte byte nbt storage
bool boolean nbt storage
short short nbt storage
int integer scoreboard fake player
ints integer nbt storage
long long nbt storage
float float nbt storage
double double nbt storage
string string nbt storage
arr array nbt storage
comp compound nbt storage
obj objective scoreboard objective
// define regular variable
var foo str = "foo"

print(foo)

// define objective
var bar obj(dummy) = "displayName"

print(bar[@a])

operations

to operate variables use <var> <operator> <var> or <var> <assign> <expression>. note: you can only operate int and obj variables.

foo += bar

foo = bar + baz

melon variable operators pretty much copy those of minecraft score operations except < and > as those are going to be used in conditions. another difference from default operators, melon allows to operate without assigning, for example, instead of += you can just + and use that in expressions.

there are also special operators for incrementing and decrementing variables by 1.

// increment
foo++

// decrement
foo--

store result / success

you can also store result or success of a command in int and obj variables.

// store result
foo = random 1..5 // return random number from 1 to 5

// store success
foo ?= random 1..5 // return 1 on success, 0 otherwise

compile-time variables

use & prefix to create a compile-time variable.

// define
var &foo str = "foo";

// use like normal variable
print(&foo) // print() is shortcut for `tellraw @a`
// compiles to:
tellraw @a "foo"

// or embed anywhere search-n-replace style
loot give @s loot test:bar_&(foo)_baz
// is treated like
loot give @s loot test:bar_foo_baz

short definition form

use the define operator, :=. melon will automatically assume the type of the variable. and if you want float double or any other nbt stored number, you have to use the vanilla postfixes for numbers, for more info check out nbt format on minecraft wiki.

foo := "bar" // str
bar := 3.14f // float

exceptions

to define nbt stored integer use the special i postfix.

foo := 1  // int
bar := 2i // ints

as for scoreboard objectives, you cannot define them using short definition form.

how run-time variables work under the hood

when you create a variable, in the compiled datapack its just setting var.<variable_name> to the value you give it, in the nspace:zzz data storage to the value you gave your variable. e.g.:

var foo str = "foo"
// compiles to:
// data modify storage namespace:zzz var.foo set value "bar"

although its different when you create integer variables. it actually stores your integer in .<var_name> fake player in the "namespace.zzz.var" scoreboard

var foo int = 8
// compiles to:
// scoreboard players set .foo namespace.zzz.var 8

when using variables in functions like print() it will be embedded properly. e.g.

print(foo)
// compiles to
tellraw @a {"storage":"test:zzz", "nbt":"var.foo"}

strings

formatted string (f-string)

formatted strings are inspired by python's f-strings, offer a convenient and more readable way to create dynamic strings by embedding variables, expressions, and formatting directly in text.

to use f-strings put f before a string. then anywhere in the string open curly braces {} and type any minecraft color, hex color code, or style. separate different formatting options with comma.

print(f"{green, bold, italic}hello world!")

to embed variables or expressions you should type variable name, insert formatting options after a semi-colon. insert an ! at the end to make formatting apply only to the variable / expression.

x := 2
print(f"x is equal to {x; red, bold!}, x+2 is equal to {x + 2; red, bold}")

more complex text components: