{b}RFTools Control Manual

Table of Contents:
{l:intro}Introduction
{l:programmer}Programmer
{l:processor}Processor
{l:networking}Networking
{l:craftingstation}Crafting Station
{l:workbench}Workbench
{l:items}Moving Items
{l:sharing}Sharing Programs
{/}



{l:concepts}Programming Concepts
{l:types}Types
{l:parameters}Parameters
{l:variables}Variables
{l:events}Events
{l:opcodes}Opcode Types
{l:concurrency}Concurrency
{l:debugging}Debugging
{-------------------------------------------------------------}
{b}Introduction
{n:intro}
RFTools Control is an addon mod for RFTools which adds a visual
programming system that is suitable for automation tasks. Programs
written with RFTools Control can move items around, interact with
redstone, examine energy levels of machines and so on. There is direct
support for the storage scanner and in the future it will also give
auto crafting abilities to that scanner.

Don't be too afraid of the word 'programming' though. Programs written
for RFTools Control are typically very simple and they are also written
in a visual manner. That means you don't actually have to 'write' code.
Instead you drag icons on a grid.
{-------------------------------------------------------------}
{b}The Programmer
{n:programmer}
{rb:programmer}
The Programmer is the basic block where you create your programs. To
use it you need to insert a program card item:
{ri:program_card}
{-------------------------------------------------------------}
The programmer gui can seem complicated at first but it is not that
hard. At the left side you can see all the available opcodes that you
can use in your programs. You can click and drag them onto the big
grid in the middle.

When an opcode is in the main grid you can connect it to neighbours
by clicking a side. If that side turns green you have made a connection
going from that opcode (the one with the green side) to the adjacent
one. Some opcodes (tests) have two outputs. There is also a red output
which indicates the negative path to follow (if the test fails)

If a connector is missing a 'stop' opcode is automatically inserted.
{-------------------------------------------------------------}
Every program needs an event to start with. An event opcode describes
what needs to happen before a program can start. Note that you can
have multiple events on the same card (and thus multiple programs) and
the same program string (connected opcodes) can even have multiple
events which indicate different entry points in the same program.

There are currently seven events: redstone pulse on, redstone pulse
off, timer, exception, signal, craft, and craft resume.
{-------------------------------------------------------------}
Many opcodes have parameters. When you select an opcode on the main
grid you get a list of all possible parameters below the gui.
Parameters are typed but many conversions are done automatically (for
example, an integer is automatically converted to a string when
that is required).

You can specify a parameter in three different ways: as a constant
value, as a variable, or as a function. Variables are stored in
the processor (more on that later). An important function is 'last'
which simply returns the last result of the previous opcode. This
is important, many opcodes have a result which you can access with
this function.
{-------------------------------------------------------------}
{b}The Processor
{n:processor}
{rb:processor}
The Processor is the device that actually runs your programs. First you
write a program with the Programmer and then you insert that card in
the processor. Up to 6 program cards are supported. The Processor needs
some more modules before it can really work though.
{-------------------------------------------------------------}
The most important thing that the Processor needs is at least one cpu
core. For every core that you install in one of the 16 expansion slots
you can run an additional program at the same time. Note that cpu cores
are expensive but you don't always need many even if you plan to run
multiple programs because typical programs don't run very long.

There are three tiers of cpu cores. They differ in their execution speed
and the RF/t energy consumption.
{-------------------------------------------------------------}
The Processor can store up to 32 variables. To do that it needs RAM chips.
Every RAM chip adds 8 variables so maximum 4 RAM chips are supported.

Variables can be used by programs but to do that you have to allocate the
variables to the right card slot. To do that there are six small buttons
above the card slots. Pressing such a button will switch the gui to
'allocation' mode. Then you can select the variables and mark them green.
The first variable marked green will be index 0 for programs on that card.
And so on. Note that the variable index you use in programs is relative
to how you allocated the variables!

You can allocate variables that are already used by other cards. That way
it is possible to share information between programs on different cards.
{-------------------------------------------------------------}
The Processor also has access to 24 internal item slots. These are
always available but just like the variables you also have to allocate
them for each card. Again slot numbers used in programs are relative
to how you allocated them. i.e. slot 0 will be the first slot you
allocated for a program running in a specific program slot.
{-------------------------------------------------------------}
{b}Networking
{n:networking}
Using a network card and several nodes:
{ri:network_card}
{rb:node}
you can create a network. A processor has only six sides but using
a network you can extend this by also enabling access to the sides
of all nodes that are connected to the network.
{-------------------------------------------------------------}
After installing a network card you need to set it up. This can be
done with the 'net setup <name>' console command (in the Processor
console). The <name> will be the network name and is also used
in all the nodes that want to connect to this network.

Setting up the network card will also initiate the scan to find
all nodes that match the given channel name (in a 17x17x17 area
with the processor at the center). Note that the network card is
also needed to connect to crafting stations which this scan will
also pick up.
{-------------------------------------------------------------}
{b}Crafting Station
{n:craftingstation}
{rb:craftingstation}
The Crafting Station is a device from which you can request items to
be crafted through a program that you write yourselves and that runs
on a nearby Processor. To have the Processor work with a Crafting
Station it needs a network card.

Crafting operations can sometimes take a long time and the gui of
this station shows operations that are still in progress.
{-------------------------------------------------------------}
Note that what a crafting station essentially does is show you for
which items a processor has 'craft' events enabled. As soon as you
request the crafting of such an item the resulting program will be
executed. But what you do in that program is fully up to you.
In many cases you would probably make a program that actually crafts
the desired result but you can also do other things so you can
use the crafting station as a way to trigger various actions to
happen. For example, you can have a 'craft redstone' event that
actually just turns on processing of various items and then a
'craft coal' event to turn it off again. It is up to you.
{-------------------------------------------------------------}
{b}Workbench
{n:workbench}
{rb:workbench}
The Workbench is a normal crafting device with an internal buffer for
items. It can be used just like that. However, it's main use is in automation
as this workbench supports piping out the crafted result from the bottom.
In addition a program running on a Processor can directly input ingredients
for a recipe in the workbench from the top side.

The internal buffer of the Workbench is often used for crafting cards to
help with autocrafting setups.
{-------------------------------------------------------------}
{b}Moving Items
{n:items}
Many programs will move items at some point. It is important to note that
the processor cannot move items directly from one inventory to another.
Items always have to go through the processor itself. That's why you
typically need 'fetch' and 'push' items after each other.

For many opcodes where you can access a normal inventory you can
also access a storage system linked to a storage scanner. To do that
you need to insert a storage screen module from RFTools into one of
the 16 expansion slots of the Processor. Then to use this feature you
just leave the 'inventory' parameter empty and it should access
the storage where supported.
{-------------------------------------------------------------}
{b}Sharing Programs
{n:sharing}
The programmer supports the clipboard. You select opcodes, you can type
Ctrl-C and the selected grid will be copied to the clipboard. This is a
JSON file that you can share on the web. If you have such a program in
your clipboard you can do Ctrl-V to paste it. If the program is small
enough you can paste it in a section of your grid by clicking on the
grid location where you want the left-top opcode to appear. If you
select nothing it will try to place from the top-left corner. Note that
it will merge what is in the clipboard with what is already there.

Note that you can always use Ctrl-Z to undo this.

To select opcodes you can use Ctrl-A for the entire grid or else
ctrl-click for a single opcode and ctrl-double click for a sequence.
{-------------------------------------------------------------}
{b}Programming Concepts
{n:concepts}
A program in RFTools Control is made out of 'opcodes' that are
arranged on a grid. Opcodes connect to other opcodes (through a
green arrow or a red arrow in case of a test opcode) and they have
parameters that can influence what they can do.

The tooltip on an opcode in the programmer will give more
information (press shift for even more information)
{-------------------------------------------------------------}
{b}Types
{n:types}
Parameters and variables are typed. That means that they have a specific
type (like integer, string, ...) and need to be converted to be used as
something else. Many conversions are done automatically. For example,
if you need a string but the last result was an integer then the integer
will automatically be converted into a string.

The following types are currently implemented: string, integer, float,
boolean, side (represents a side of the processor or one of the connected
nodes), inventory (represents an inventory adjacent to the processor or a
connected node and an optional side from which to access the inventory),
item (an itemstack), and exception.
{-------------------------------------------------------------}
{b}Parameters
{n:parameters}
As mentioned before opcodes can have multiple parameters which control
how the opcode works. Parameters always have a specific type. Many
parameters are optional which you can see in the tooltip.

Every parameter can be either a constant value, a reference to a
variable, or a function. If you open the parameter editor in the
programmer (the ... button) you can select between these three options
with the buttons at the top.

The available list of functions depends on the type of the parameter.
Some types have no functions defined for them (yet).
{-------------------------------------------------------------}
{b}Variables
{n:variables}
A processor can store up to 32 variables. These are also typed just
like parameters. Make sure to allocate the variables to the card slot
that you need them for. All programs that are on the same card slot
will share those variables automatically.

You can also share variables with programs on other slots because
it is possible to allocate a given variable to multiple cards.

Note that accessing variables in programs needs a relative index.
So variable 0 in a program means the first allocated variable for
that card.
{-------------------------------------------------------------}
{b}Events
{n:events}
Programs written with RFTools Control are 'event driven'. That means they
only start when there is some kind of event. An event can be a redstone
pulse, a timer, a crafting request for some item and more.

Most events have parameters that control when they are fired.

Every program sequence (connected opcodes) on a card will need at least
one event. Otherwise it can never run. It is possible to connect multiple
events to the same program sequence.

If an event fires it is executed on an available core. If no cores are
available then it will be put in a waiting list. Except for the timer event.
That one is discared if there are no cores available.
{-------------------------------------------------------------}
{b}Opcode Types
{n:opcodes}
The following types of opcodes are available:
  * Events: at least one of them is needed for every program
  * Operation: the standard operations
  * Evaluate: an evaluation opcode. These typically do some
    calculation or check and set the result for the next
    opcode to use
  * Test: these opcodes perform a boolean test and then do
    a branch based on that test. Therefore these opcodes have
    two outputs (a green and a red output)
  * Wire: there is only one wire opcode. It is meant to connect
    opcodes that are not adjacent
{-------------------------------------------------------------}
{b}Concurrency
{n:concurrency}
As soon as you have multiple cores in your processor multiple programs
can run at the same time. There are a few problems with this. First you
must make sure that slots and variables are properly allocated in case
where these programs don't share that info. This is the easy case.

But sometimes you want to share data. For example, if you have one
program putting items in some internal slots and another program getting
them out again. To handle this safely you might sometimes want to use
locks. A lock is global to the processor (for all programs on that
processor) and it has a name. Only one program can hold a lock with some
name. Other programs that want that lock will wait until the lock is
available again. Make sure to always restore locks! If you forget
you can use 'reset' to reset your processor and clean everything.
{-------------------------------------------------------------}
Another problem with concurrency is preventing one program to use up
all the cores. For example, if you have a program that needs some time
to execute and executes whenever there is a redstone signal then if
you give two signals very quickly there might be multiple instances of
that program running (if there are sufficient cores available).

Sometimes this is ok but in many cases you might want only one instance
of a given program running at every time. To do that you can use the
'single' parameter that you can set with every event. If you make that
true then this event can only be fired once and it will be locked until
the program that was attached to that event stops running.
{-------------------------------------------------------------}
{b}Debugging
{n:debugging}
You will make bugs. Repeat after me: you will make bugs! So what can you
do to fix those bugs? There are a few techniques. First there is a 'log'
opcode that you can use to dump messages on the console. It can show
simple messages or even the contents of variables.

But for more advanced debugging you might want to use the internal
debugger. To use that you simply go to the processor and type:
    db debug

This will halt all programs that might currently be running and allow you
to selectively singlestep them (i.e. execute them one instruction at a
time).
{-------------------------------------------------------------}
To see where a specific program is at you can use:
    db info

To singlestep a program running on (for example) core 0 you would type:
    db s 0

This will execute the current instruction and show you the next
instruction that is waiting for you to execute.
You can also examine the last result with:
    db last 0

(or 'db last' to show all last results for all current programs)
{-------------------------------------------------------------}
While the program is being single stepped you can of course also
examine variables by clicking the '...' button on the left (and
change them).

To resume all programs you do:
    db resume
{-------------------------------------------------------------}
