cc-haxe/doc/Concepts.md

5.9 KiB

Use this if you want to know how the OS works.

Network

Every computer has a id assigned by the mod. It is a unique number that identifies the computer and cannot be changed. The native implementation of the network stack works with channels. If you listen on a channel you will receive all messages sent to that channel. Every computer listens to the channel with its id and a brodcast channel. The broadcast channel is used for Routing Tables and GPS packets.

Network messages can be forwarded by other computers. This is done by the Routing Table. The routing algorithm prefers wire over wireless connections.

Packages also have a time-to-live (TTL) value. This is used to prevent packages from being forwarded forever. You will get a response if a package is dropped because of TTL.

There is also a concept of protocols. A protocol is used to distinguish between different types of packages. A protocol is basically a string and that is used to forward packages to the correct handler. You can use registerProto to listen for packages with a specific protocol.

There are 2 ways of sending messages to other computers: sendAndAwait and sendAndForget. sendAndAwait will wait for a response from the remote computer and return it. sendAndForget will send the message and return immediately and does not care about the response. You can compare it to UDP and TCP.

Usage

import net.Net;

var data = {"foo": "bar"};

Net.instance.sendAndAwait(netID,"protoname",data).map((response)->{
    switch (response){
        case Success(data):
            trace(data);
        case Failure(error):
            trace(error);
    }
});

Net.instance.registerProto("res",(pack: GenericPackage)->{
    var requestPack: Package<MyType> = cast pack; // Try not to use Dynamic

    requestPack.respond("Hello Back");
});

Peripherals

Peripherals are devices that are connected to the computer. They can be used to interact with the world. Every peripheral has an address and a type. The address can be "back" or "right" to refer to the peripheral on the back or right side of the computer or something like "energyCell_0" to refer to something connected via cable. Peripherals can be accessed via the Peripheral class.

Also peripherals can be made accessible via the network. More on that later.

Usage

var back = Peripheral.getRedstone("back");
back.setOutput(true);

var drive Peripheral.getDrive("drive_0");
drive.eject();

GUI

If you want to write something to the screen you have to create a WindowContext via the WindowManager. This allows programs to write to the screen without interfering with each other.

There are currently 2 types of WindowContext: the BufferedVirtualTermWriter that stores the state of the screen in a buffer and prints it to the screen when it is activeted and the StatelessVirtualTermWriter which calls a render method when it is activated. Currently i prefer the StatelessVirtualTermWriter because its not so heavy on the RAM but both work.

They both can be used just like the nativ implmentation.

Usage

var ctx = WindowManager.createNewBufferedContext();
ctx.setCursorPos(0, 0);
ctx.setCursorBlink(false);
ctx.setBackgroundColor(Blue);
ctx.setForegroundColor(White);
ctx.write("Hello world!");

Under the hood

There are a number of interfaces and classes that needs to be explained to understand how the GUI works.

TermWriteable is an interface that allows the usage of the normal CC terminal write methods. Stuff like write, setCursorPos and setCursorBlink are defined here. This is of course implemented by the physical screens and the main terminal.

Most of the time you will not write directory to a real screen but to a VirtualTermWriter which extends TermWriteable with some more methods like enable and setTarget. The setTarget is used as the proxy target of a VirtualTermWriter and with enable and disable you can enable and disable the forwarding of the write methods to the target.

The StatelessVirtualTermWriter and BufferedVirtualTermWriter are both VirtualTermWriter. They can have a real output as a target. Or they can have another VirtualTermWriter as target like the BufferedVirtualTermWriter which uses a TermBuffer as an intermediate target.

All of that is just for printing to the screen. If you want to read input you have to use the WindowContext which is a TermWriteable. WindowContext also handles events like onClick or onKey. This is need so that the right program gets the input depending on the active window on the screen or terminal.

All of the WindowContext are managed by the WindowManager. The WindowManager also delegates the events to the right WindowContext.

GUI helper classes

Because we want a more abstract way of writing to the screen we have some "helper" classes. I call them "helper" but they a very essential to the GUI.

First there is the Pixel class which is nothing more that a char and a foreground and background color.

A collection of Pixel is called a Canvas which is nothing more than a 2D array of Pixel with some functions strapped to it.

Proceses

The concept of processes tryes to encapsulate programs. A process is basically an interface with the run(handle: ProcessHandle) method. The idea is that you can register all you disposable resources in the handle and they will be disposed when the process is killed or crashes.

A process can be used as a command on the terminal or as a service. See bin/HelloWorld.hx for an example. Basically everything that runs and is not part of the kernel is a process.

In order for you program to be used it needs to be registered in the BinStore and the DCEHack manually.

EndOfLoop

You can imagine the whole runtime like the event loop is JS. The EndOfLoop class is used to register callbacks that are called at the end of the loop. This is like the setTimeout(0, callback) in JS.