Redstone Programming Language

Last version (1.2) download!

Version 1.0 overview: http://www.youtube.com/watch?v=q-l0Q5lhm6Q
Minecraft Forum thread: http://www.minecraftforum.net/forums/mapping...

RPL quick facts:

  • Currently exists as MCEdit filter
  • Generates cammand blocks and some other redstone based on a text script
  • Has some new cool commands and selectors
  • Tremendously simplifies work with operations: @Sheep obj1 = obj2 /= var obj3 += 5
  • Has cool text-replacement capabilities: @p obj<<1:5>> = 0 becomes @p obj1 = 0, @p obj2 = 0, ... , @p obj5 = 0
  • And much more!

Changelog for 1.2:

  • Added trigonometric functions: sin and cos
  • Replacements are now also applied in directives
  • Added #repeater directive
  • New comparison option for selectors: @a[objective==1]
  • Unknown selectors now turn into entity`s name: @zombling means @e[name=zombling]

Changelog for 1.1:

  • Added #new_onetimeline directive
  • Added #used_objectives directive
  • Added #coords directive
  • Added support for decimal numbers in ranges: <<0.2:-0.2:-0.05>>
  • Replaced @Sheeps selector with @Sheep

Documentation

RPL is intended to convert the code from a text file to set of command blocks in Minecraft world. So most of the lines in RPL program transform into one or several (or even hundreds) command blocks. There are also lines which affect RPL's behavior and don't appear in the resulted blocks. You can also write comments after a double slash ("//") at any point in RPL program.

Special RPL directives tell the interpreter how to process the lines coming after them. Every directive always starts with "#" symbol and takes a separate line (except #coords). There are 8 directives in RPL now. Let's go through all of them.

#replace

This one tells the interpreter that the following lines contain a set of replacement pairs. RPL will memorize these pairs and later apply the replacements on all the lines that are intended to turn into command blocks, as well as directives. In each line pairs should be separated by two following symbols: "; ", a semicolon and a space. Each pair should have this format: find = replace. So "=" should have a space on each side. No quotes needed. Multi-line replacements are not supported. Here's an example:

#replace
%1000% = thousand Constant; %100% = hundred Constant; my_coords = 239 123 -45
no_ai = {NoAI:1,Silent:1}; mob_type = Creeper
NEW MOB = summon mob_type my_coords no_ai

Replacements are applied in the reverse order, so after this example all occurences of NEW MOB will be turned into summon Creeper 239 123 -45 {NoAI:1,Silent:1}

#new_line

This directive means that the following lines should be transformed into command blocks which will be placed in a straight line in the Minecraft world. The direction and coordinates of that line`s starting block are set via directive`s attributes which go right after the directive itself like so:

#new_line x 12 57 -34

So the first attribute is direction and it has 3 possible values: x, y and z. Negative directions are not supported because they make little sense due to the fact that in Minecraft generally blocks are updated and executed in the order of positive directions along each axis.

The second, third and fourth arguments here are x, y and z of the first block in the line. You can use standart Minecraft tilde notation here to specify the position relative to the corner of your MCEdit selection with lowest coordinates along each axis.

#new_clockline

This directive is intended to be used with 20Hz clocks. It creates a fill-based clock, which makes a line of redstone blocks which are being replaced with stone and then vice-versa 20 times per second (each game tick). So every command block touching that line gets powered and updated 20 times per second and executes its command with the same frequency. RPL places all the command blocks following this directive around that line in exactly the same order they will be triggered ingame each tick. There is an optional attribute that lets you specify the sides of the clockline you want to use to place command blocks next to:

#new_clockline z ~ ~1 ~ bottom,left
#new_clockline x ~ ~2 ~ all

So this directive has 5 parameters. Unlike #new_line, the first one can only be x or z. The last attribute can be either all or a set of comma-separated available options: right,left,top,bottom. Default value is all.

And both in #new_line and in #new_clockline modes a blank line will cause a one-block gap between resulting command blocks.

#new_functionline

This one is exactly the same as #new_clockline except it doesn't create a 20Hz clock, but you can place a redstone block at the beginning of the line and the whole line will be triggered and the redstone block will be replaced with stone, so you will be able to place it there again later. This way it's kinda like a "function" that you can call.

#new_onetimeline

Same as #new_functionline, but the line gets removed after the first execution. RPL places a block at the end of the line that fills the whole thing with air. This is useful for things like creating objectives and setting up some initial values.

#used_objectives

RPL will generate a set of command blocks that creates all objectives used in the script above. It only counts objectives from selectors (like in score_obj_min=0 and obj<=4) and from operations. It has two optional parameters. The first one specifies the criteria of the objectives (like dummy, trigger, deathCount etc.), the default is dummy. The second one is whether or not you want to remove existing objectives with same names before creating new ones (it will just erase all data from them). If you do, add reset to the directive. Here's some possible usages of this directive:

#used_objectives
#used_objectives reset
#used_objectives trigger
#used_objectives deathCount reset

#coords(~ ~ ~)

Replaces itself with absolute coordinates of the block which is specified in the brackets relative to the MCEdit selection. So if you selected a block with coordinates 20 60 40 then this example

stats block #coords(~1 ~2 ~3) set SuccessCount result test

will turn into this:

stats block 21 62 43 set SuccessCount result test

This applies after all the replacements and after "<<...>>" thing described below.

#repeater

This directive only works in #new_line mode and allows you to place a repeater. It can take a separate line or go at the end of the line like this:

tp @p ~<<1:3>> ~ ~ #repeater 3 r

The code above will generate 3 command blocks and 3 repeaters. This directive have two arguments, the first one is repeater`s delay (can be from 1 to 4, default is 1), and the second one is whether or not you want the repeaters to look in the reverse direction. You can use just #repeater if you want a repeater with delay of 1 facing the same direction as your command block line.

Here's a complete script of a simple walking animation for an armor stand:

#replace
%from = -45; %to = 45; %step = 5

#new_line x ~ ~1 ~
entitydata @woodenGuy {Pose:{LeftLeg:[<<%from:%to:%step>>f,,]}} #repeater

#new_line x ~ ~1 ~1
// put a button on the first command block of this line
entitydata @woodenGuy {Pose:{RightLeg:[<<%to:%from:-%step>>f,,]}} #repeater
// place a repeater facing from the last command block of this line to the last command block of the next line

#new_line x ~ ~1 ~3
// place a repeater facing from the first command block of this line to the first command block of the previous line (a block with a button)
entitydata @woodenGuy {Pose:{LeftLeg:[<<%from:%to:%step>>f,,]}} #repeater r

#new_line x ~ ~1 ~4
entitydata @woodenGuy {Pose:{RightLeg:[<<%to:%from:-%step>>f,,]}} #repeater r

#new_onetimeline x ~ ~1 ~7 left
//place a redstone block in ~ ~1 ~7. It will create an armor stand and remove the command block.
summon ArmorStand ~ ~1 ~ {CustomName:woodenGuy,NoGravity:1,NoBasePlate:1,ShowArms:1}

That's about it for directives, now to the actual command goodness!

Commands

RPL is intended to make writing commands easier so it has some tools to simplify this process and reduce the amount of code you write. The first tool is what you may call an "options" tool. It lets you specify different text options for the portion of the line so the line will be copied with every option you specified. Here's an example:

@Creepers <<scoreA,scoreB>> = 10

will turn into:

@Creepers scoreA = 10
@Creepers scoreB = 10

You can also set ranges for numbers:

testfor @p {SelectedItemSlot:<<0:6:2>>,Inventory:[{Slot:<<0:6:2>>b,tag:{display:{name:"Basic Sword"}}}]}

turns into:

testfor @p {SelectedItemSlot:0,Inventory:[{Slot:0b,tag:{display:{name:"Basic Sword"}}}]}
testfor @p {SelectedItemSlot:2,Inventory:[{Slot:2b,tag:{display:{name:"Basic Sword"}}}]}
testfor @p {SelectedItemSlot:4,Inventory:[{Slot:4b,tag:{display:{name:"Basic Sword"}}}]}
testfor @p {SelectedItemSlot:6,Inventory:[{Slot:6b,tag:{display:{name:"Basic Sword"}}}]}

So you use double angle brackets for it and there can be two types of syntax inside them: comma-separated strings or ranges in one of two following formats: min:max or min:max:step. As you can see above, you can use multiple sets of options in the same line and RPL will use them respectively. You can also mix text options with ranges as long as you keep the same amount of options in each brackets.

For each command RPL reads from a file it first applies all the replacements defined in #replace sections above it, then it checks for these angle brackets and duplicates the line if needed, and then it proceeds to further interpretation of each of the resulting commands.

Preserving original formatting

There's a way to avoid any replacements or interpretation of your command whatsoever, and that is by adding $ symbol at the beginning of the line. If RPL sees a $ as a first symbol of the line, it removes it and makes a command block out of it right away, without even removing comments.

Selectors

The next thing is advansed selectors. RPL introduces a bunch of new selectors and simplifies your work with them a little bit. Here's all the features:

1. Entity selectors. There's a selector for each type of entity: @Creepers, @Boats, @ItemFrames and so on. They are just short versions of @e[type=Creeper], @e[type=Boat] etc. You can still add variables to them like normal: @Zombies[r=5] stands for @e[type=Zombie,r=5]. Here is a complete list of all new selectors:

Mobs: Bats, Blazes, CaveSpiders, Chickens, Cows, Creepers, EnderDragons, Endermans, Endermites, Ghasts, Giants, Guardians, Horses, IronGolems, LavaSlimes, Mooshrooms, Ocelots, Pigs, PigZombies, Rabbits, Sheep, Silverfish, Skeletons, Slimes, SnowGolems, Spiders, Squids, Villagers, Witches, WitherBosses, Wolfs, Zombies.
Projectiles: Arrows, Snowballs, Eggs, Fireballs, SmallFireballs, ThrownEnderpearls, ThrownExpBottles, ThrownPotions, WitherSkulls.
Items: Items, XPOrbs.
Vehicles: Boats, Minecarts, MinecartChests, MinecartFurnaces, MinecartSpawners, MinecartTNTs, MinecartHoppers, MinecartCommandBlocks.
Dynamic Tiles: PrimedTnts, FallingSand.
Other: ArmorStands, EnderCrystals, EyeOfEnderSignals, FireworksRockets, ItemFrames, LeashKnots, Paintings.

2. @me selector. This is short version of @e[r=0,c=1] and it's useful in "execute" commands to specify the entity you are executing the command from.

3. More clear comparison: @Sheep[deltav>=0] stands for @Sheep[score_deltav_min=0] and @Sheep[deltav<=-1] stands for @Sheep[score_deltav=-1]. So <= and >= signs are allowed in selectors, but there should be a number on the right side. You can also do this: @Sheep[-2<=deltav<=2]. And one more option: @Sheep[deltav==2]. This is the same as @Sheep[2<=deltav<=2].

4. "Name" selectors. Unknown selectors will turn into entity`s name. Example: @zombling means @e[name=zombling].

5. New selector variable: block. This is based on "detect" feature of the "execute" command. Basically you can check for a block right in the selector. This command will kill all the sheep standing on grass:

kill @Sheep[block=~ ~-0.5 ~ grass]
So after block= you should set x, y and z, absolute or relative to the entity (sheep in our case), and a block type. Optionally you can set a data value for the block, default is -1: @Sheep[block=~ ~-0.5 ~ stone 2] This selector variable can't be used twice in the same line.

Short "execute"

Just a small feature: you can use => sign instead of execute *** ~ ~ ~. Example:

@Sheep[xbounce>=1] => @a => playsound dig.wood @p[r=0]

stands for:

execute @e[type=Sheep,score_xbounce_min=1] ~ ~ ~ execute @a ~ ~ ~ playsound dig.wood @p[r=0]

So @selector => command turns into execute @selector ~ ~ ~ command

Operations

And now to probably the most handy feature of RPL: intuitive operations. You don't have to write those loooong "scoreboard players operation" or "scoreboard players set" or "add" or "remove", you can just write a few intuitive words and RPL will do the rest for you:

@Sheep vx = vy

This command will set the score of each sheep in "vx" objective to its score in "vy" objective. If you are interested, it corresponds to this Minecraft command:

execute @e[type=Sheep] ~ ~ ~ scoreboard players operation @e[r=0,c=1] vx = @e[r=0,c=1] vy

In this case the RPL command is 6 times shorter and probably 10 times more clear!
So there always should be two words on the left side of the operation: selector and objective. On the right side you can use either selector and objective or just an objective, RPL will use @me selector by default.
Numbers are also allowed on the right side, but only for "=", "-=" and "+=" operations. If you use numbers, you can add a dataTag on the right just like in "scoreboard players set/add/remove" commands:

@Creepers powered = 1 {powered:1b}

So this is pretty cool, but there's more :) You can cascade the operations with the same left side:

@Sheep temp = deltav /= dirScale settings *= temp

means:

@Sheep temp = deltav
@Sheep temp /= dirScale settings
@Sheep temp *= temp

The important thing here is that operation`s priorities are NOT considered. The operations are executed in the same order as they appear in the string. For example:

@Sheep a = 2 += 3 *= d

means:

@Sheep a = 2
@Sheep a += 3
@Sheep a *= d

So "a" will be "5 * d", but not "2 + (3 * d)" as you would expect if priorities were considered.

The other important thing is that as of now you are not allowed to use the scoreboard players operation command in RPL, because it will confuse the operation signs with its own format. The only way to use this command in RPL is by using $ sign described above. But RPL implements all the features of this command, so you probably won't need to use it anyway.

New commands

RPL introduces some new commands. Currently there are four of them.

tpsmart

This command allows you to teleport entities based on its score in an objective. You can have an objective that contains velocity values for each entity and teleport them accordingly. I will use the term "velocity" below because it is the most probable usecase of this command. This command creates a set of command blocks and each one of them covers certain range in possible velocity values. It takes 8 parameters:

tpsmart @Sheep x vx 20 400 10 0.02 0.4

1. Selector - who do you want to telepot
2. Axis of teleportation. You can use only one axis per one tpsmart command
3. Objective to use. RPL with use the selector from the first parameter to determine the velocity value
4 and 5. Range of possible velocity values.
6. Step. This affects how many blocks will be created and how accurate the correspondence between velocity and tp distance will be. In the above example step is 10, so the command will create a command block for velocity values from 20 to 30, then from 30 to 40 and so on.
7 and 8. The range of distances corresponding to specified range of velocity values. This is the distance the entity will be teleported by. If you are using a 20Hz clock the reasonable values for these parameters are between -1 and 1, 1 stands for 20 blocks per second.

The above example will generate these commands:

tp @e[type=Sheep,score_vx_min=20,score_vx=29] ~0.02 ~ ~
tp @e[type=Sheep,score_vx_min=30,score_vx=39] ~0.03 ~ ~
tp @e[type=Sheep,score_vx_min=40,score_vx=49] ~0.041 ~ ~
... and so on untill:
tp @e[type=Sheep,score_vx_min=380,score_vx=389] ~0.39 ~ ~
tp @e[type=Sheep,score_vx_min=390,score_vx=400] ~0.4 ~ ~

sqrt

Square root calculation. As of now there's no way to actually calculate the root in Minecraft, so this command uses the same technique as tpsmart. It creates a command block for every possible resulting square root and each of these blocks checks if the source number is around this block`s number squared, if that makes sense. Example:

sqrt 1 5 @p src dest

converts into (in RPL syntax):

@p[1<=src<=2] dest = 1
@p[3<=src<=6] dest = 2
@p[7<=src<=12] dest = 3
@p[13<=src<=20] dest = 4
@p[21<=src<=30] dest = 5

So the first two parameters set the range of resulting square roots you want to get, 3rd and 4th parameters specify the source number and last two parameters specify where to put the square root. In the example above there's only one parameter for it because RPL will use @me selector by default. Full syntax looks like this:

sqrt 1 6 @srcSelector srcObj @destSelector destObj

and it will be converted to (in RPL syntax again):

@srcSelector[1<=srcObj<=2] => destSelector destObj = 1
@srcSelector[3<=srcObj<=6] => destSelector destObj = 2
@srcSelector[7<=srcObj<=12] => destSelector destObj = 3
@srcSelector[13<=srcObj<=20] => destSelector destObj = 4
@srcSelector[21<=srcObj<=30] => destSelector destObj = 5
@srcSelector[31<=srcObj<=42] => destSelector destObj = 6

sin & cos

Just what it looks like.

sin @srcSelector srcObj @destSelector destObj 180 1000

Arguments:
1 and 2. Where to take a value from. This must be a number from 0 to 359 (in degrees). You can also use rx and ry as objective to refer to player`s rotation.
3 and 4. Where to put the result.
5. Number of steps. In this example 180 comand blocks will be generated for angles: 0 to 1, 2 to 3, 4 to 5 and so on. Use 360 here if you want to check every possible angle.
6. Multiplier. Your sine or cosine will be multiplied by this number. In this example @destSelector destObj will contain a number from -1000 to 1000.