Skip to content

A programming language that runs in Minecraft BE by compiling into commands

License

Notifications You must be signed in to change notification settings

CBerJun/AcaciaMC

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Acacia

English | 中文

Introduction

Acacia is a programming language that runs in Minecraft Bedrock Edition. Minecraft commands can be complicated, long and hard to maintain. Acacia is an alternative to commands -- it is also used to control Minecraft. However, Acacia code is much more readable than commands, which increases the maintainability of your project and your productivity. Imagine writing a Tetris game that runs in Minecraft using less than 14KB code (see below)!

Acacia code is finally compiled into .mcfunction files. In other word, Acacia code will be converted into Minecraft commands by the program, and can be loaded in a Minecraft world as a behavior pack.

Still confused? Here's a simple Acacia program that calculates sum of elements in an arithmetic sequence in Minecraft:

import print
def arithmetic(start: int, to: int, delta=1) -> int:
    #*
     * Return sum of arithmetic sequence that starts with `start`,
     * ends with `to` with common difference `delta`.
     *#
    result (start + to) * ((to - start) / delta + 1) / 2
res := arithmetic(-30, 14, delta=2)
print.tell(print.format("Sum of arithmetic sequence (-30~14, d=2) is %0", res))

Acacia will convert the above code into commands:

# These efficient commands are AUTO-GENERATED! Isn't that cool?
scoreboard players set acacia1 acacia -30
scoreboard players set acacia2 acacia 14
scoreboard players set acacia3 acacia 2
scoreboard players operation acacia4 acacia = acacia1 acacia
scoreboard players operation acacia4 acacia += acacia2 acacia
scoreboard players operation acacia5 acacia = acacia2 acacia
scoreboard players operation acacia5 acacia -= acacia1 acacia
scoreboard players operation acacia5 acacia /= acacia3 acacia
scoreboard players add acacia5 acacia 1
scoreboard players operation acacia4 acacia *= acacia5 acacia
scoreboard players operation acacia4 acacia /= acacia6 acacia
scoreboard players operation acacia7 acacia = acacia4 acacia
tellraw @a {"rawtext": [{"text": "Sum of arithmetic sequence (-30~14, d=2) is "}, {"score": {"objective": "acacia", "name": "acacia7"}}]}
# Initialization: add scoreboard and set constants.
scoreboard objectives add acacia dummy
scoreboard players set acacia6 acacia 2

Running these generated commands will send this message in Minecraft's chat:

Sum of arithmetic sequence (-30~14, d=2) is -184

In conclusion, by using Acacia you can create Minecraft projects -- not by writing commands, but by writing Acacia code, which is much more easier to maintain and understand.

Acacia is written in Python, so Python (3.6.1 or newer) is required by compiler (i.e. the program that converts your code into commands).

What can Acacia do?

Some real-world examples:

  • Without writing 1 command, we can create a simple Tetris game in Minecraft! The source code can be found here. It is only 14KB in size! The generated commands, however, use about 280KB and 50 files.
  • Still without 1 command, a random Minecraft maze generator can be made using 3.5KB code (with comment that explains the algorithm removed). See source code.
  • Noteblock musics can be automatically generated by the builtin module music.

Detailed features:

  • No more redundant commands and huge amount of files; Acacia code is simple.
  • No more worries about /execute context.
  • No more entity tags; Acacia has an exclusive entity system!
  • No more scoreboards! Instead we have the variable system which is popular in computer programming.
  • No more repetitive commands; Acacia is good at generating repetitive commands.
  • You can define loops and use the "if" statement to run something conditionally.
  • Acacia provides various compile-time constants, including numbers, strings, lists, maps and even world positions. This makes your map or addon more flexible.

Check out this file for more information about Acacia's syntax.

Syntax Overview

This is how to define a variable in Acacia: a := 1. That's it. No need for scoreboards.

Nested expressions within 1 line of code:

a := 10
b := (10 + a) * a - 5

Function definitions:

def foo(x: int, y = True) -> int:
    # Here is function body code
    res := x
    if y:
        res += 10
    result res  # return value
z: int
# These are all valid:
foo(1)
z = foo(2, False)
z = foo(x=3)

Flow control statements (selections and loops):

def is_prime(x: int) -> bool:
    #* Test if `x` is a prime number *#
    res := True
    mod: int = 2
    while mod <= x / 2:
        if x % mod == 0:
            res = False
        mod += 1
    result res

Various builtin modules:

import print
money := 10
# Send "Hello, world!" in chat to everyone
print.tell("Hello world!")
# Show "Money: (Value of variable `money`)" on actionbar to everyone
print.title(print.format("Money: %0", money), mode=print.ACTIONBAR)
import music
# Generate a noteblock music and use 1.2x speed.
const m = music.Music("music_score.mid", speed=1.2)
m.play()

Use of constants and for to avoid repetitive code:

import world

# Place concretes of different colors according to value of an variable
const COLORS = {
    0: "cyan", 1: "orange", 2: "yellow",
    3: "purple", 4: "lime", 5: "red", 6: "blue"
}
i := 0  # Calculate `i`...
for c in COLORS:
    # `for` instructs the compiler to generate the following code
    # repetitively for you!
    if c == i:
        world.setblock(
            Pos(0, -50, 0),
            world.Block("concrete", {"color": COLORS[c]})
        )

Position and entity system:

import world

const ORIGIN = AbsPos(0, -50, 0)
world.fill(ORIGIN, Offset(x=5, z=5),
           world.Block("concrete", {"color": "red"}))

entity Test:
    new():
        new(type="armor_stand", pos=ORIGIN)
        world.setblock(Pos(self), "diamond_block")
        world.effect_give(self, "invisibility", duration=1000)

    def foo():
        world.tp(self, ORIGIN)

test_group := Engroup[Test]()
instance := Test()
test_group.add(instance)
test_group.select(Enfilter().distance_from(ORIGIN, max=5))
for test in test_group:
    test.foo()

Discover More about Acacia

About

A programming language that runs in Minecraft BE by compiling into commands

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages