Compare commits

..

12 Commits

Author SHA1 Message Date
088fce0aaa made ServiceManager a static class 2023-07-30 15:48:22 +02:00
3b3c69ee56 made GPS and INS a static class 2023-07-30 15:45:30 +02:00
5a9d463192 made GPS a static class 2023-07-30 15:42:02 +02:00
97c906e013 made Net a static class 2023-07-30 15:38:46 +02:00
505d318ffb made Routing a static class 2023-07-30 15:35:43 +02:00
89f209130e made BinStore a static class 2023-07-27 20:45:37 +02:00
74d0232160 made WindowManager a static class 2023-07-27 20:41:23 +02:00
9deea0ee98 made peripherals a static class 2023-07-27 20:38:23 +02:00
a93ee1cddf made Log static class 2023-07-27 20:35:36 +02:00
e1e0180502 changed kernel events to static class 2023-07-27 20:30:39 +02:00
adc5ab1849 makefile watch all files 2023-07-27 20:30:11 +02:00
1a523cb3ce added startup file 2023-07-27 20:15:41 +02:00
44 changed files with 451 additions and 467 deletions

View File

@@ -46,7 +46,7 @@ clean:
.PHONY: watch
watch:
find src -name "*.hx" | entr make debug
find src | entr make debug
.PHONY: emulator
emulator:

View File

@@ -26,7 +26,7 @@ import net.Net;
var data = {"foo": "bar"};
Net.instance.sendAndAwait(netID,"protoname",data).map((response)->{
Net.sendAndAwait(netID,"protoname",data).map((response)->{
switch (response){
case Success(data):
trace(data);
@@ -35,7 +35,7 @@ Net.instance.sendAndAwait(netID,"protoname",data).map((response)->{
}
});
Net.instance.registerProto("res",(pack: GenericPackage)->{
Net.registerProto("res",(pack: GenericPackage)->{
var requestPack: Package<MyType> = cast pack; // Try not to use Dynamic
requestPack.respond("Hello Back");
@@ -54,10 +54,10 @@ Also peripherals can be made accessible via the network. More on that later.
## Usage
```haxe
var back = Peripheral.instance.getRedstone("back");
var back = Peripheral.getRedstone("back");
back.setOutput(true);
var drive Peripheral.instance.getDrive("drive_0");
var drive Peripheral.getDrive("drive_0");
drive.eject();
```
@@ -73,7 +73,7 @@ They both can be used just like the [nativ implmentation](https://tweaked.cc/mod
## Usage
```haxe
var ctx = WindowManager.instance.createNewBufferedContext();
var ctx = WindowManager.createNewBufferedContext();
ctx.setCursorPos(0, 0);
ctx.setCursorBlink(false);
ctx.setBackgroundColor(Blue);

View File

@@ -9,7 +9,7 @@ using Lambda;
class Disk extends CLIAppBase {
public function new() {
registerSyncSubcommand("ls", (args)->{
Peripheral.instance.getAllDrives().foreach(drive -> {
Peripheral.getAllDrives().foreach(drive -> {
var addr = drive.getAddr();
var label = drive.getDiskLabel();
var id = drive.getDiskID();
@@ -53,7 +53,7 @@ class Disk extends CLIAppBase {
}
var driveAddr = args[0];
var drive = Peripheral.instance.getDrive(driveAddr);
var drive = Peripheral.getDrive(driveAddr);
if (drive == null){
handle.writeLine("Drive not found: " + driveAddr);
@@ -76,7 +76,7 @@ class Disk extends CLIAppBase {
}
var driveAddr = args[0];
var drive = Peripheral.instance.getDrive(driveAddr);
var drive = Peripheral.getDrive(driveAddr);
var label:String = args[1];
if (drive == null){
@@ -102,7 +102,7 @@ class Disk extends CLIAppBase {
}
private function audioDiskPlayPause(driveAddr: String, play: Bool): Bool {
var drive = Peripheral.instance.getDrive(driveAddr);
var drive = Peripheral.getDrive(driveAddr);
if (drive == null){
handle.writeLine("Drive not found: " + driveAddr);

View File

@@ -16,13 +16,13 @@ class GPS extends CLIAppBase {
var pos: Pos3 = new Vec3<Float>(x, y, z);
kernel.gps.GPS.instance.setManualPosition(pos);
kernel.gps.GPS.setManualPosition(pos);
return true;
},"<x> <y> <z>");
registerSyncSubcommand("status",(args)->{
var pos = kernel.gps.GPS.instance.getPosition();
var pos = kernel.gps.GPS.getPosition();
if (pos != null) {
handle.writeLine('Position x:${pos.x} y:${pos.y} z:${pos.z}');
} else {
@@ -30,7 +30,7 @@ class GPS extends CLIAppBase {
return true;
}
var acc = kernel.gps.GPS.instance.getAccuracy();
var acc = kernel.gps.GPS.getAccuracy();
if (acc == 1){
handle.writeLine("Accuracy: Low");
} else if (acc == 2){
@@ -39,7 +39,7 @@ class GPS extends CLIAppBase {
handle.writeLine("Accuracy: High");
}
var ins = INS.instance.getHeading();
var ins = INS.getHeading();
if (ins != null) {
handle.writeLine('INS heading: ${ins.x} y:${ins.y} z:${ins.z}');
} else {
@@ -50,7 +50,7 @@ class GPS extends CLIAppBase {
});
registerAsyncSubcommand("locate",(args)->{
return kernel.gps.GPS.instance.locate().map((pos)->{
return kernel.gps.GPS.locate().map((pos)->{
if (pos != null) {
handle.writeLine('Position x:${pos.x} y:${pos.y} z:${pos.z}');
} else {
@@ -61,7 +61,7 @@ class GPS extends CLIAppBase {
});
registerAsyncSubcommand("ins",(args)->{
return INS.instance.align().map((_)->{
return INS.align().map((_)->{
handle.writeLine("INS aligned");
return true;
});

View File

@@ -7,7 +7,7 @@ class ID implements Process {
public function new() {}
public function run(handle:ProcessHandle) {
handle.writeLine("ID: " + kernel.net.Net.instance.networkID);
handle.writeLine("ID: " + kernel.net.Net.networkID);
handle.close();
}
}

View File

@@ -24,7 +24,7 @@ class KernelLog implements Process {
statelessCtx.setRenderFunc(this.render);
Log.instance.onLog.handle(()->{
Log.onLog.handle(()->{
statelessCtx.requestRender();
});
}
@@ -33,7 +33,7 @@ class KernelLog implements Process {
ctx.clear();
ctx.setCursorPos(0,0);
var lines = Log.instance.getLines();
var lines = Log.getLines();
var height = ctx.getSize().y;
var start = MathI.max(lines.length - height,0);

View File

@@ -9,7 +9,7 @@ using tink.CoreApi;
class Net extends CLIAppBase {
public function new() {
registerSyncSubcommand("route", (args)->{
var routes = Routing.instance.getRouteTable();
var routes = Routing.getRouteTable();
for(k => v in routes) {
handle.writeLine('${k} => ${v.interf.name()}(${v.cost})');
@@ -19,7 +19,7 @@ class Net extends CLIAppBase {
});
registerSyncSubcommand("iface", (args)->{
var modems = Peripheral.instance.getAllModems();
var modems = Peripheral.getAllModems();
for (modem in modems) {
handle.writeLine(modem.name());
@@ -29,7 +29,7 @@ class Net extends CLIAppBase {
});
registerSyncSubcommand("proto",(args)->{
var protos = kernel.net.Net.instance.getActiveProtocols();
var protos = kernel.net.Net.getActiveProtocols();
for (proto in protos) {
handle.writeLine(proto);
@@ -50,7 +50,7 @@ class Net extends CLIAppBase {
return Future.sync(false);
}
return kernel.net.Net.instance.ping(toID).map(result -> {
return kernel.net.Net.ping(toID).map(result -> {
switch (result){
case Success(_):
handle.write("Ping succeeded");

View File

@@ -8,7 +8,7 @@ class Perf extends CLIAppBase {
registerSyncSubcommand("inspect",(args)->{
if (args.length < 1) return false;
var result = Peripheral.instance.inspect(args[0]);
var result = Peripheral.inspect(args[0]);
if (result == null){
handle.writeLine("No peripheral found on side "+args[0]);
@@ -29,8 +29,8 @@ class Perf extends CLIAppBase {
},"<side>");
registerSyncSubcommand("list",(args)->{
for (addr in Peripheral.instance.getAllAddresses()){
handle.writeLine('$addr => ${Peripheral.instance.getTypes(addr).join(", ")}');
for (addr in Peripheral.getAllAddresses()){
handle.writeLine('$addr => ${Peripheral.getTypes(addr).join(", ")}');
}
return true;
});

View File

@@ -8,17 +8,17 @@ using tink.CoreApi;
class Redstone extends CLIAppBase{
public function new() {
registerSyncSubcommand("on", (args)-> {
Peripheral.instance.getRedstone(args[0]).setOutput(true);
Peripheral.getRedstone(args[0]).setOutput(true);
return true;
},"<side>");
registerSyncSubcommand("off", (args)-> {
Peripheral.instance.getRedstone(args[0]).setOutput(false);
Peripheral.getRedstone(args[0]).setOutput(false);
return true;
},"<side>");
registerSyncSubcommand("get", (args)-> {
var value = Peripheral.instance.getRedstone(args[0]).getAnalogInput();
var value = Peripheral.getRedstone(args[0]).getAnalogInput();
handle.write("Analog input: " + value);
return true;
},"<side>");

View File

@@ -14,7 +14,7 @@ class Service extends CLIAppBase {
var name = args[0];
var result = ServiceManager.instance.start(name);
var result = ServiceManager.start(name);
return handleResult(result);
},"<name>");
@@ -25,7 +25,7 @@ class Service extends CLIAppBase {
var name = args[0];
var result = ServiceManager.instance.stop(name);
var result = ServiceManager.stop(name);
return handleResult(result);
},"<name>");
@@ -38,7 +38,7 @@ class Service extends CLIAppBase {
var binName = args[1];
var rest = args.slice(2);
var result = ServiceManager.instance.register(name, binName, rest);
var result = ServiceManager.register(name, binName, rest);
return handleResult(result);
},"<name> <binary> [args...]");
@@ -49,13 +49,13 @@ class Service extends CLIAppBase {
var name = args[0];
var result = ServiceManager.instance.unregister(name);
var result = ServiceManager.unregister(name);
return handleResult(result);
},"<name>");
registerSyncSubcommand("list", (args) ->{
var list = ServiceManager.instance.listRunning();
var list = ServiceManager.listRunning();
for (name in list) {
this.handle.writeLine(name);
@@ -69,7 +69,7 @@ class Service extends CLIAppBase {
return false;
}
ServiceManager.instance.enable(args[0]);
ServiceManager.enable(args[0]);
return true;
},"<name>");
}

View File

@@ -200,7 +200,7 @@ class Terminal implements Process {
}
private function getProgByName(name:String):Process {
var bin = BinStore.instance.getBinByAlias(name);
var bin = BinStore.getBinByAlias(name);
if (bin == null) {
return null;
}

View File

@@ -25,7 +25,7 @@ class Res extends CLIAppBase {
},"<url>");
registerAsyncSubcommand("register",(args)->{
var srv: Null<ResManager> = ServiceManager.instance.get("resmgr");
var srv: Null<ResManager> = ServiceManager.get("resmgr");
var addr = args[0];
var name = args[1];
@@ -35,7 +35,7 @@ class Res extends CLIAppBase {
return false;
}
var perf: kernel.peripherals.Redstone = Peripheral.instance.getRedstone(addr);
var perf: kernel.peripherals.Redstone = Peripheral.getRedstone(addr);
if (perf == null) {
handle.writeLine("Error: peripheral not found");

View File

@@ -21,7 +21,7 @@ class ResManager implements Process {
public function run(handle:ProcessHandle) {
this.handle = handle;
Net.instance.registerProto("res",handlePackage);
Net.registerProto("res",handlePackage);
load();
}
@@ -53,7 +53,7 @@ class ResManager implements Process {
}
private function registerName(id: String){
return RessourceNames.register(id, Net.instance.networkID);
return RessourceNames.register(id, Net.networkID);
}
private function persist(){
@@ -73,7 +73,7 @@ class ResManager implements Process {
var savedExports: Array<{name: String, addr: String, type: String}> = store.get("exports",[]);
for (export in savedExports){
var perph = Peripheral.instance.getFromType(export.addr,export.type);
var perph = Peripheral.getFromType(export.addr,export.type);
if (perph == null){
handle.writeLine('Could not load export: ${export.name} on ${export.addr}');

View File

@@ -35,14 +35,14 @@ class PFClient implements Process {
}
private function render() {
var acc = kernel.gps.GPS.instance.getAccuracy();
var pos: Pos3 = kernel.gps.GPS.instance.getPosition() ?? {x: 0, y: 0, z: 0};
var acc = kernel.gps.GPS.getAccuracy();
var pos: Pos3 = kernel.gps.GPS.getPosition() ?? {x: 0, y: 0, z: 0};
var childre: Array<UIElement> = [
new TextElement('Acc: ${acc}'),
new TextElement('Pos: X:${pos.x} Y:${pos.y} Z:${pos.z}'),
new TextElement('UPDATE', { style: {bgColor: Gray}, uiEvents: {onClick: () -> {
kernel.gps.GPS.instance.locate().handle((pos) ->{
kernel.gps.GPS.locate().handle((pos) ->{
this.requestRender();
});
}}}),

View File

@@ -25,7 +25,7 @@ class SiteRessourceController implements Process {
load();
// Register proto
kernel.net.Net.instance.registerProto(SITE_CONTROLLER_RESSOURCE_MANAGER_PROTO, this.handleMsg);
kernel.net.Net.registerProto(SITE_CONTROLLER_RESSOURCE_MANAGER_PROTO, this.handleMsg);
}
private function handleMsg(pkg:GenericPackage) {

View File

@@ -24,42 +24,36 @@ class Init {
public static function initKernel() {
// Init singeltons here because haxe is confused about the order to create them.
Log.instance = new Log();
KernelEvents.instance = new KernelEvents();
Peripheral.instance = new Peripheral();
Log.init();
KernelEvents.init();
WindowManager.instance = new WindowManager();
WindowManager.init();
MainTerm.instance = new MainTerm();
BinStore.instance = new BinStore();
if (Turtle.isTurtle()){
Turtle.instance = new Turtle();
}
Routing.instance = new Routing();
Net.instance = new Net();
Routing.init();
Net.init();
GPS.instance = new GPS();
INS.instance = new INS();
GPS.init();
// Register default terminate handler
KernelEvents.instance.onTerminate.handle(_->{
KernelEvents.instance.shutdown();
KernelEvents.onTerminate.handle(_->{
KernelEvents.shutdown();
});
Debug.printBuildInfo();
Routing.instance.init();
if (!FS.exists("/var/ns")) {
FS.makeDir("/var/ns");
}
Init.mainEvent = MainLoop.add(()->{
KernelEvents.instance.startEventLoop();
KernelEvents.startEventLoop();
});
ServiceManager.instance = new ServiceManager();
ServiceManager.init();
}
}

View File

@@ -18,124 +18,122 @@ class KernelEvents {
/**
Depends on: (Nothing)
**/
public static var instance:KernelEvents;
public final onAlarm:Signal<Int>;
public final onChar:Signal<String>;
public final onDisk:Signal<String>;
public final onDiskEject:Signal<String>;
public final onHttpCheck:Signal<{url:String, success:Bool, failReason:Any}>;
public final onHttpFailure:Signal<{url:String, failReason:String, handle:HTTPResponse}>;
public final onHttpSuccess:Signal<{url:String, handle:HTTPResponse}>;
public final onKey:Signal<{keyCode:Int, isHeld:Bool}>;
public final onKeyUp:Signal<Int>;
public final onModemMessage:Signal<{
public static var onAlarm(default, null):Signal<Int>;
public static var onChar(default, null):Signal<String>;
public static var onDisk(default, null):Signal<String>;
public static var onDiskEject(default, null):Signal<String>;
public static var onHttpCheck(default, null):Signal<{url:String, success:Bool, failReason:Any}>;
public static var onHttpFailure(default, null):Signal<{url:String, failReason:String, handle:HTTPResponse}>;
public static var onHttpSuccess(default, null):Signal<{url:String, handle:HTTPResponse}>;
public static var onKey(default, null):Signal<{keyCode:Int, isHeld:Bool}>;
public static var onKeyUp(default, null):Signal<Int>;
public static var onModemMessage(default, null):Signal<{
addr:String,
channel:Int,
replyChannel:Int,
message:Dynamic,
distance:Null<Float>
}>;
public final onMonitorResize:Signal<String>;
public final onMonitorTouch:Signal<{addr:String, pos:Pos}>;
public final onMouseClick:Signal<{button:ButtonType, pos:Pos}>;
public final onMouseDrag:Signal<{button:ButtonType, pos:Pos}>;
public final onMouseScroll:Signal<{dir:Int, pos:Pos}>;
public final onMouseUp:Signal<{button:ButtonType, pos:Pos}>;
public final onPaste:Signal<String>;
public final onPeripheral:Signal<String>;
public final onPeripheralDetach:Signal<String>;
public final onRedstone:Signal<Noise>;
public final onSpeakerAudioEmpty:Signal<String>;
public final onTaskComplete:Signal<{id:Int, success:Bool, failedReason:String}>;
public final onTermResize:Signal<Noise>;
public final onTerminate:Signal<Noise>;
public final onTimer:Signal<Int>;
public final onTurtleInventory:Signal<Noise>;
public final onWebsocketClose:Signal<String>;
public final onWebsocketFailure:Signal<{url:String, failReason:String}>;
public final onWebsocketMessage:Signal<{url:String, message:String, isBinary:Bool}>;
public final onWebsocketSuccess:Signal<{url:String, handle:Any}>;
public static var onMonitorResize(default, null):Signal<String>;
public static var onMonitorTouch(default, null):Signal<{addr:String, pos:Pos}>;
public static var onMouseClick(default, null):Signal<{button:ButtonType, pos:Pos}>;
public static var onMouseDrag(default, null):Signal<{button:ButtonType, pos:Pos}>;
public static var onMouseScroll(default, null):Signal<{dir:Int, pos:Pos}>;
public static var onMouseUp(default, null):Signal<{button:ButtonType, pos:Pos}>;
public static var onPaste(default, null):Signal<String>;
public static var onPeripheral(default, null):Signal<String>;
public static var onPeripheralDetach(default, null):Signal<String>;
public static var onRedstone(default, null):Signal<Noise>;
public static var onSpeakerAudioEmpty(default, null):Signal<String>;
public static var onTaskComplete(default, null):Signal<{id:Int, success:Bool, failedReason:String}>;
public static var onTermResize(default, null):Signal<Noise>;
public static var onTerminate(default, null):Signal<Noise>;
public static var onTimer(default, null):Signal<Int>;
public static var onTurtleInventory(default, null):Signal<Noise>;
public static var onWebsocketClose(default, null):Signal<String>;
public static var onWebsocketFailure(default, null):Signal<{url:String, failReason:String}>;
public static var onWebsocketMessage(default, null):Signal<{url:String, message:String, isBinary:Bool}>;
public static var onWebsocketSuccess(default, null):Signal<{url:String, handle:Any}>;
private final onAlarmTrigger:SignalTrigger<Int> = Signal.trigger();
private final onCharTrigger:SignalTrigger<String> = Signal.trigger();
private final onDiskTrigger:SignalTrigger<String> = Signal.trigger();
private final onDiskEjectTrigger:SignalTrigger<String> = Signal.trigger();
private final onHttpCheckTrigger:SignalTrigger<{url:String, success:Bool, failReason:Any}> = Signal.trigger();
private final onHttpFailureTrigger:SignalTrigger<{url:String, failReason:String, handle:HTTPResponse}> = Signal.trigger();
private final onHttpSuccessTrigger:SignalTrigger<{url:String, handle:HTTPResponse}> = Signal.trigger();
private final onKeyTrigger:SignalTrigger<{keyCode:Int, isHeld:Bool}> = Signal.trigger();
private final onKeyUpTrigger:SignalTrigger<Int> = Signal.trigger();
private final onModemMessageTrigger:SignalTrigger<{
private static final onAlarmTrigger:SignalTrigger<Int> = Signal.trigger();
private static final onCharTrigger:SignalTrigger<String> = Signal.trigger();
private static final onDiskTrigger:SignalTrigger<String> = Signal.trigger();
private static final onDiskEjectTrigger:SignalTrigger<String> = Signal.trigger();
private static final onHttpCheckTrigger:SignalTrigger<{url:String, success:Bool, failReason:Any}> = Signal.trigger();
private static final onHttpFailureTrigger:SignalTrigger<{url:String, failReason:String, handle:HTTPResponse}> = Signal.trigger();
private static final onHttpSuccessTrigger:SignalTrigger<{url:String, handle:HTTPResponse}> = Signal.trigger();
private static final onKeyTrigger:SignalTrigger<{keyCode:Int, isHeld:Bool}> = Signal.trigger();
private static final onKeyUpTrigger:SignalTrigger<Int> = Signal.trigger();
private static final onModemMessageTrigger:SignalTrigger<{
addr:String,
channel:Int,
replyChannel:Int,
message:Dynamic,
distance:Null<Float>
}> = Signal.trigger();
private final onMonitorResizeTrigger:SignalTrigger<String> = Signal.trigger();
private final onMonitorTouchTrigger:SignalTrigger<{addr:String, pos:Pos}> = Signal.trigger();
private final onMouseClickTrigger:SignalTrigger<{button:ButtonType, pos:Pos}> = Signal.trigger();
private final onMouseDragTrigger:SignalTrigger<{button:ButtonType, pos:Pos}> = Signal.trigger();
private final onMouseScrollTrigger:SignalTrigger<{dir:Int, pos:Pos}> = Signal.trigger();
private final onMouseUpTrigger:SignalTrigger<{button:ButtonType, pos:Pos}> = Signal.trigger();
private final onPasteTrigger:SignalTrigger<String> = Signal.trigger();
private final onPeripheralTrigger:SignalTrigger<String> = Signal.trigger();
private final onPeripheralDetachTrigger:SignalTrigger<String> = Signal.trigger();
private final onRednetMessageTrigger:SignalTrigger<{sender:Int, message:Any, protocol:Any}> = Signal.trigger();
private final onRedstoneTrigger:SignalTrigger<Noise> = Signal.trigger();
private final onSpeakerAudioEmptyTrigger:SignalTrigger<String> = Signal.trigger();
private final onTaskCompleteTrigger:SignalTrigger<{id:Int, success:Bool, failedReason:String}> = Signal.trigger();
private final onTermResizeTrigger:SignalTrigger<Noise> = Signal.trigger();
private final onTerminateTrigger:SignalTrigger<Noise> = Signal.trigger();
private final onTimerTrigger:SignalTrigger<Int> = Signal.trigger();
private final onTurtleInventoryTrigger:SignalTrigger<Noise> = Signal.trigger();
private final onWebsocketCloseTrigger:SignalTrigger<String> = Signal.trigger();
private final onWebsocketFailureTrigger:SignalTrigger<{url:String, failReason:String}> = Signal.trigger();
private final onWebsocketMessageTrigger:SignalTrigger<{url:String, message:String, isBinary:Bool}> = Signal.trigger();
private final onWebsocketSuccessTrigger:SignalTrigger<{url:String, handle:Any}> = Signal.trigger();
private static final onMonitorResizeTrigger:SignalTrigger<String> = Signal.trigger();
private static final onMonitorTouchTrigger:SignalTrigger<{addr:String, pos:Pos}> = Signal.trigger();
private static final onMouseClickTrigger:SignalTrigger<{button:ButtonType, pos:Pos}> = Signal.trigger();
private static final onMouseDragTrigger:SignalTrigger<{button:ButtonType, pos:Pos}> = Signal.trigger();
private static final onMouseScrollTrigger:SignalTrigger<{dir:Int, pos:Pos}> = Signal.trigger();
private static final onMouseUpTrigger:SignalTrigger<{button:ButtonType, pos:Pos}> = Signal.trigger();
private static final onPasteTrigger:SignalTrigger<String> = Signal.trigger();
private static final onPeripheralTrigger:SignalTrigger<String> = Signal.trigger();
private static final onPeripheralDetachTrigger:SignalTrigger<String> = Signal.trigger();
private static final onRednetMessageTrigger:SignalTrigger<{sender:Int, message:Any, protocol:Any}> = Signal.trigger();
private static final onRedstoneTrigger:SignalTrigger<Noise> = Signal.trigger();
private static final onSpeakerAudioEmptyTrigger:SignalTrigger<String> = Signal.trigger();
private static final onTaskCompleteTrigger:SignalTrigger<{id:Int, success:Bool, failedReason:String}> = Signal.trigger();
private static final onTermResizeTrigger:SignalTrigger<Noise> = Signal.trigger();
private static final onTerminateTrigger:SignalTrigger<Noise> = Signal.trigger();
private static final onTimerTrigger:SignalTrigger<Int> = Signal.trigger();
private static final onTurtleInventoryTrigger:SignalTrigger<Noise> = Signal.trigger();
private static final onWebsocketCloseTrigger:SignalTrigger<String> = Signal.trigger();
private static final onWebsocketFailureTrigger:SignalTrigger<{url:String, failReason:String}> = Signal.trigger();
private static final onWebsocketMessageTrigger:SignalTrigger<{url:String, message:String, isBinary:Bool}> = Signal.trigger();
private static final onWebsocketSuccessTrigger:SignalTrigger<{url:String, handle:Any}> = Signal.trigger();
private var stopLoop:Bool = false;
private static var stopLoop:Bool = false;
@:allow(kernel.Init)
private function new() {
this.onAlarm = onAlarmTrigger.asSignal();
this.onChar = onCharTrigger.asSignal();
this.onDisk = onDiskTrigger.asSignal();
this.onDiskEject = onDiskEjectTrigger.asSignal();
this.onHttpCheck = onHttpCheckTrigger.asSignal();
this.onHttpFailure = onHttpFailureTrigger.asSignal();
this.onHttpSuccess = onHttpSuccessTrigger.asSignal();
this.onKey = onKeyTrigger.asSignal();
this.onKeyUp = onKeyUpTrigger.asSignal();
this.onModemMessage = onModemMessageTrigger.asSignal();
this.onMonitorResize = onMonitorResizeTrigger.asSignal();
this.onMonitorTouch = onMonitorTouchTrigger.asSignal();
this.onMouseClick = onMouseClickTrigger.asSignal();
this.onMouseDrag = onMouseDragTrigger.asSignal();
this.onMouseScroll = onMouseScrollTrigger.asSignal();
this.onMouseUp = onMouseUpTrigger.asSignal();
this.onPaste = onPasteTrigger.asSignal();
this.onPeripheral = onPeripheralTrigger.asSignal();
this.onPeripheralDetach = onPeripheralDetachTrigger.asSignal();
this.onRedstone = onRedstoneTrigger.asSignal();
this.onSpeakerAudioEmpty = onSpeakerAudioEmptyTrigger.asSignal();
this.onTaskComplete = onTaskCompleteTrigger.asSignal();
this.onTermResize = onTermResizeTrigger.asSignal();
this.onTerminate = onTerminateTrigger.asSignal();
this.onTimer = onTimerTrigger.asSignal();
this.onTurtleInventory = onTurtleInventoryTrigger.asSignal();
this.onWebsocketClose = onWebsocketCloseTrigger.asSignal();
this.onWebsocketFailure = onWebsocketFailureTrigger.asSignal();
this.onWebsocketMessage = onWebsocketMessageTrigger.asSignal();
this.onWebsocketSuccess = onWebsocketSuccessTrigger.asSignal();
private static function init() {
onAlarm = onAlarmTrigger.asSignal();
onChar = onCharTrigger.asSignal();
onDisk = onDiskTrigger.asSignal();
onDiskEject = onDiskEjectTrigger.asSignal();
onHttpCheck = onHttpCheckTrigger.asSignal();
onHttpFailure = onHttpFailureTrigger.asSignal();
onHttpSuccess = onHttpSuccessTrigger.asSignal();
onKey = onKeyTrigger.asSignal();
onKeyUp = onKeyUpTrigger.asSignal();
onModemMessage = onModemMessageTrigger.asSignal();
onMonitorResize = onMonitorResizeTrigger.asSignal();
onMonitorTouch = onMonitorTouchTrigger.asSignal();
onMouseClick = onMouseClickTrigger.asSignal();
onMouseDrag = onMouseDragTrigger.asSignal();
onMouseScroll = onMouseScrollTrigger.asSignal();
onMouseUp = onMouseUpTrigger.asSignal();
onPaste = onPasteTrigger.asSignal();
onPeripheral = onPeripheralTrigger.asSignal();
onPeripheralDetach = onPeripheralDetachTrigger.asSignal();
onRedstone = onRedstoneTrigger.asSignal();
onSpeakerAudioEmpty = onSpeakerAudioEmptyTrigger.asSignal();
onTaskComplete = onTaskCompleteTrigger.asSignal();
onTermResize = onTermResizeTrigger.asSignal();
onTerminate = onTerminateTrigger.asSignal();
onTimer = onTimerTrigger.asSignal();
onTurtleInventory = onTurtleInventoryTrigger.asSignal();
onWebsocketClose = onWebsocketCloseTrigger.asSignal();
onWebsocketFailure = onWebsocketFailureTrigger.asSignal();
onWebsocketMessage = onWebsocketMessageTrigger.asSignal();
onWebsocketSuccess = onWebsocketSuccessTrigger.asSignal();
}
/**
Start pulling events. Blocking.
**/
@:allow(kernel.Init)
private function startEventLoop() {
private static function startEventLoop() {
while (!stopLoop) {
var event:Table<Int, Dynamic> = pullEvents();
@@ -148,45 +146,45 @@ class KernelEvents {
}
}
public function shutdown() {
public static function shutdown() {
// clearing screens
for (screen in Peripheral.instance.getAllScreens()) {
for (screen in Peripheral.getAllScreens()) {
screen.reset();
}
Log.info('Shutting down event loop');
this.stopLoop = true;
stopLoop = true;
MainTerm.instance.reset();
Init.mainEvent.stop();
}
private function pullEvents():Table<Int, Dynamic> {
private static function pullEvents():Table<Int, Dynamic> {
return cast TableTools.pack(Coroutine.yield(null));
}
private function fireSignal(eventName: String,event:Table<Int, Dynamic> ) {
private static function fireSignal(eventName: String,event:Table<Int, Dynamic> ) {
switch eventName {
case "alarm":
this.onAlarmTrigger.trigger(event[2]);
onAlarmTrigger.trigger(event[2]);
case "char":
this.onCharTrigger.trigger(event[2]);
onCharTrigger.trigger(event[2]);
case "disk":
this.onDiskTrigger.trigger(event[2]);
onDiskTrigger.trigger(event[2]);
case "disk_eject":
this.onDiskEjectTrigger.trigger(event[2]);
onDiskEjectTrigger.trigger(event[2]);
case "http_check":
this.onHttpCheckTrigger.trigger({url: event[2], success: event[3], failReason: event[4]});
onHttpCheckTrigger.trigger({url: event[2], success: event[3], failReason: event[4]});
case "http_failure":
this.onHttpFailureTrigger.trigger({url: event[2], failReason: event[3], handle: event[4]});
onHttpFailureTrigger.trigger({url: event[2], failReason: event[3], handle: event[4]});
case "http_success":
this.onHttpSuccessTrigger.trigger({url: event[2], handle: event[3]});
onHttpSuccessTrigger.trigger({url: event[2], handle: event[3]});
case "key":
this.onKeyTrigger.trigger({keyCode: event[2], isHeld: event[3]});
onKeyTrigger.trigger({keyCode: event[2], isHeld: event[3]});
case "key_up":
this.onKeyUpTrigger.trigger(event[2]);
onKeyUpTrigger.trigger(event[2]);
case "modem_message":
this.onModemMessageTrigger.trigger({
onModemMessageTrigger.trigger({
addr: event[2],
channel: event[3],
replyChannel: event[4],
@@ -194,45 +192,45 @@ class KernelEvents {
distance: event[6]
});
case "monitor_resize":
this.onMonitorResizeTrigger.trigger(event[2]);
onMonitorResizeTrigger.trigger(event[2]);
case "monitor_touch":
this.onMonitorTouchTrigger.trigger({addr: event[2], pos: {x: (event[3] : Int) - 1, y: (event[4] : Int) - 1}});
onMonitorTouchTrigger.trigger({addr: event[2], pos: {x: (event[3] : Int) - 1, y: (event[4] : Int) - 1}});
case "mouse_click":
this.onMouseClickTrigger.trigger({button: ccButtonToEnum(event[2]), pos: {x: (event[3] : Int) - 1, y: (event[4] : Int) - 1}});
onMouseClickTrigger.trigger({button: ccButtonToEnum(event[2]), pos: {x: (event[3] : Int) - 1, y: (event[4] : Int) - 1}});
case "mouse_drag":
this.onMouseDragTrigger.trigger({button: ccButtonToEnum(event[2]), pos: {x: (event[3] : Int) - 1, y: (event[4] : Int) - 1}});
onMouseDragTrigger.trigger({button: ccButtonToEnum(event[2]), pos: {x: (event[3] : Int) - 1, y: (event[4] : Int) - 1}});
case "mouse_scroll":
this.onMouseScrollTrigger.trigger({dir: event[2], pos: {x: (event[3] : Int) - 1, y: (event[4] : Int) - 1}});
onMouseScrollTrigger.trigger({dir: event[2], pos: {x: (event[3] : Int) - 1, y: (event[4] : Int) - 1}});
case "mouse_up":
this.onMouseUpTrigger.trigger({button: ccButtonToEnum(event[2]), pos: {x: (event[3] : Int) - 1, y: (event[4] : Int) - 1}});
onMouseUpTrigger.trigger({button: ccButtonToEnum(event[2]), pos: {x: (event[3] : Int) - 1, y: (event[4] : Int) - 1}});
case "paste":
this.onPasteTrigger.trigger(event[2]);
onPasteTrigger.trigger(event[2]);
case "peripheral":
this.onPeripheralTrigger.trigger(event[2]);
onPeripheralTrigger.trigger(event[2]);
case "peripheral_detach":
this.onPeripheralDetachTrigger.trigger(event[2]);
onPeripheralDetachTrigger.trigger(event[2]);
case "redstone":
this.onRedstoneTrigger.trigger(null);
onRedstoneTrigger.trigger(null);
case "speaker_audio_empty":
this.onSpeakerAudioEmptyTrigger.trigger(event[2]);
onSpeakerAudioEmptyTrigger.trigger(event[2]);
case "task_complete":
this.onTaskCompleteTrigger.trigger({id: event[2], success: event[3], failedReason: event[4]});
onTaskCompleteTrigger.trigger({id: event[2], success: event[3], failedReason: event[4]});
case "term_resize":
this.onTermResizeTrigger.trigger(null);
onTermResizeTrigger.trigger(null);
case "terminate":
this.onTerminateTrigger.trigger(null);
onTerminateTrigger.trigger(null);
case "timer":
this.onTimerTrigger.trigger(event[2]);
onTimerTrigger.trigger(event[2]);
case "turtle_inventory":
this.onTurtleInventoryTrigger.trigger(null);
onTurtleInventoryTrigger.trigger(null);
case "websocket_closed":
this.onWebsocketCloseTrigger.trigger(event[2]);
onWebsocketCloseTrigger.trigger(event[2]);
case "websocket_failure":
this.onWebsocketFailureTrigger.trigger({url: event[2], failReason: event[3]});
onWebsocketFailureTrigger.trigger({url: event[2], failReason: event[3]});
case "websocket_message":
this.onWebsocketMessageTrigger.trigger({url: event[2], message: event[3], isBinary: event[4]});
onWebsocketMessageTrigger.trigger({url: event[2], message: event[3], isBinary: event[4]});
case "websocket_success":
this.onWebsocketSuccessTrigger.trigger({url: event[2], handle: event[3]});
onWebsocketSuccessTrigger.trigger({url: event[2], handle: event[3]});
case "endofloop":
EndOfLoop.run();
default:
@@ -254,7 +252,7 @@ class KernelEvents {
}
@:allow(lib.Debug)
private function printListenerCount() {
private static function printListenerCount() {
if (onAlarmTrigger.getLength() > 0) Log.debug("onAlarm: " + onAlarmTrigger.getLength());
if (onCharTrigger.getLength() > 0) Log.debug("onChar: " + onCharTrigger.getLength());
if (onDiskTrigger.getLength() > 0) Log.debug("onDisk: " + onDiskTrigger.getLength());

View File

@@ -26,7 +26,7 @@ class MainTerm implements TermWriteable {
this.onResizeTrigger = Signal.trigger();
this.onResize = this.onResizeTrigger.asSignal();
KernelEvents.instance.onTermResize.handle(_ -> {
KernelEvents.onTermResize.handle(_ -> {
onResizeTrigger.trigger(getSize());
});
}

View File

@@ -19,7 +19,7 @@ class Timer {
timerID = OS.startTimer(timeout);
this.callback = callback;
timerLink = KernelEvents.instance.onTimer.handle(timerID -> {
timerLink = KernelEvents.onTimer.handle(timerID -> {
if (this.timerID == timerID) {
callback.invoke(null);
timerLink.cancel();

View File

@@ -22,9 +22,7 @@ import bin.Disk;
import haxe.ds.ReadOnlyArray;
class BinStore {
public static var instance: BinStore;
private final store:ReadOnlyArray<Bin> = [
private static final store:ReadOnlyArray<Bin> = [
{c: Disk, name: "Disk", aliases: ["disk"]},
{c: GPS, name: "GPS", aliases: ["gps"]},
{c: HelloWorld, name: "HelloWorld", aliases: ["hello"]},
@@ -46,12 +44,7 @@ class BinStore {
{c: PFClient, name: "PFClient", aliases: ["pfclient"]}
];
@:allow(kernel.Init)
private function new() {
}
public function getBinByName(name:String):Null<Bin> {
public static function getBinByName(name:String):Null<Bin> {
for (bin in store) {
if (bin.name == name) {
return bin;
@@ -60,7 +53,7 @@ class BinStore {
return null;
}
public function getBinByAlias(alias:String):Null<Bin> {
public static function getBinByAlias(alias:String):Null<Bin> {
for (bin in store) {
for (a in bin.aliases) {
if (a == alias) {
@@ -71,7 +64,7 @@ class BinStore {
return null;
}
public function getNameByAlias(alias: String): String {
public static function getNameByAlias(alias: String): String {
var bin = getBinByAlias(alias);
if (bin == null) {
return null;

View File

@@ -15,22 +15,20 @@ using tink.CoreApi;
You need at least 3 computers that know their position to determine the position of the computer.
**/
class GPS {
public static var instance:GPS;
private static var shouldRespond = true;
private static var shouldDoWholeNumberCheck = true;
private static var posAccuracy = 0; // 0 = unkown, 1 = (ins,best guess), 2 = (stored/manual,should be right), 3 = (gps,confirmed)
private static var cachedPosition:Pos3;
private static var lastPositionResponse: Array<{pos:Pos3,dist:Float}> = [];
private var shouldRespond = true;
private var shouldDoWholeNumberCheck = true;
private var posAccuracy = 0; // 0 = unkown, 1 = (ins,best guess), 2 = (stored/manual,should be right), 3 = (gps,confirmed)
private var cachedPosition:Pos3;
private var lastPositionResponse: Array<{pos:Pos3,dist:Float}> = [];
private var futureResolve: (pos:Null<Pos3>) -> Void = null;
private static var futureResolve: (pos:Null<Pos3>) -> Void = null;
@:allow(kernel.Init)
private function new() {
this.loadCachedPosition();
private static function init() {
loadCachedPosition();
}
public function setManualPosition(pos:Pos3) {
public static function setManualPosition(pos:Pos3) {
var kvstore = new KVStore("gps");
kvstore.set("mpos",pos);
kvstore.save();
@@ -42,39 +40,39 @@ class GPS {
}
@:allow(kernel.gps.INS)
private function setINSPosition(pos:Pos3) {
private static function setINSPosition(pos:Pos3) {
cachedPosition = pos;
posAccuracy = 1;
}
public function getPosition():Null<Pos3> {
public static function getPosition():Null<Pos3> {
return cachedPosition;
}
public function getAccuracy():Int {
public static function getAccuracy():Int {
return posAccuracy;
}
public function invalidatePosition() {
public static function invalidatePosition() {
cachedPosition = null;
posAccuracy = 0;
}
public function locate():Future<Null<Pos3>> {
public static function locate():Future<Null<Pos3>> {
// TODO: implenet a timeout
// TODO: dont send a request twice if the last one is still pending or we moved
return new Future<Null<Pos3>>((resolve)->{
this.futureResolve = resolve;
futureResolve = resolve;
sendPositionRequest();
return null;
});
}
private function resolveFuture(pos:Null<Pos3>) {
this.futureResolve(pos);
private static function resolveFuture(pos:Null<Pos3>) {
futureResolve(pos);
}
private function persistCachedPositon() {
private static function persistCachedPositon() {
if (cachedPosition == null) return;
var kvstore = new KVStore("gps");
@@ -82,7 +80,7 @@ class GPS {
kvstore.save();
}
private function loadCachedPosition() {
private static function loadCachedPosition() {
var kvstore = new KVStore("gps");
kvstore.load();
@@ -119,20 +117,20 @@ class GPS {
}
private function sendPositionRequest() {
Net.instance.brodcastGPSRequest();
private static function sendPositionRequest() {
Net.brodcastGPSRequest();
}
@:allow(kernel.net.Net)
private function handlePackage(pack:Package<Noise>, dist: Float,iface: INetworkInterface) {
private static function handlePackage(pack:Package<Noise>, dist: Float,iface: INetworkInterface) {
switch (pack.type) {
case GPSRequest:
if (!shouldRespond) return;
if (posAccuracy < 2) return;
if (cachedPosition == null) return;
var response = new Package(Net.instance.networkID,pack.fromID, pack.msgID, GPSResponse(cachedPosition),null,0);
iface.send(pack.fromID,Net.instance.networkID,response);
var response = new Package(Net.networkID,pack.fromID, pack.msgID, GPSResponse(cachedPosition),null,0);
iface.send(pack.fromID,Net.networkID,response);
case GPSResponse(pos):
if (lastPositionResponse.contains({pos:pos,dist:dist})) return; // Ignore duplicate responses
@@ -159,7 +157,7 @@ class GPS {
}
}
private function calculatePosition():Null<Pos3> {
private static function calculatePosition():Null<Pos3> {
if (lastPositionResponse.length < 3) return null;
// do a simple trilateration with the last 3 responses for now
@@ -210,7 +208,7 @@ class GPS {
/**
Determines the position(s) of a point given 3 other points and the distance to each of them.
**/
private function trilateration(p1:Pos3,p2:Pos3,p3: Pos3,r1:Float,r2:Float,r3:Float):Pair<Pos3,Pos3> {
private static function trilateration(p1:Pos3,p2:Pos3,p3: Pos3,r1:Float,r2:Float,r3:Float):Pair<Pos3,Pos3> {
var a2b = p2 - p1;
var a2c = p3 - p1;

View File

@@ -7,46 +7,39 @@ import lib.Pos3;
using tink.CoreApi;
class INS {
public static var instance:INS;
private var heading: Null<Pos3> = null;
private var alingment: Int = 1; // 0 = degraded, 1 = not aligned, 2 = aligned
@:allow(kernel.Init)
private function new() {
}
private static var heading: Null<Pos3> = null;
private static var alingment: Int = 1; // 0 = degraded, 1 = not aligned, 2 = aligned
@:allow(kernel.turtle.Turtle)
private function moveForward() {
private static function moveForward() {
if (heading == null) {
this.alingment = 0;
alingment = 0;
return;
}
move(heading);
}
@:allow(kernel.turtle.Turtle)
private function moveBackward() {
private static function moveBackward() {
if (heading == null) {
this.alingment = 0;
alingment = 0;
return;
}
move(heading.negate());
}
@:allow(kernel.turtle.Turtle)
private function moveUp() {
private static function moveUp() {
move({x: 0, y: 1, z: 0});
}
@:allow(kernel.turtle.Turtle)
private function moveDown() {
private static function moveDown() {
move({x: 0, y: -1, z: 0});
}
@:allow(kernel.turtle.Turtle)
private function turnLeft() {
private static function turnLeft() {
if (heading == null) return;
if (heading.x == 0 && heading.z == -1) {
heading = {x: -1, y: 0, z: 0};
@@ -60,7 +53,7 @@ class INS {
}
@:allow(kernel.turtle.Turtle)
private function turnRight() {
private static function turnRight() {
if (heading == null) return;
if (heading.x == 0 && heading.z == -1) {
heading = {x: 1, y: 0, z: 0};
@@ -73,18 +66,18 @@ class INS {
}
}
private function move(dir: Null<Pos3>) {
private static function move(dir: Null<Pos3>) {
Log.debug('INS move: $dir');
var pos = GPS.instance.getPosition();
var pos = GPS.getPosition();
var newPos = pos + dir;
GPS.instance.setINSPosition(newPos);
GPS.setINSPosition(newPos);
}
public function getHeading():Null<Pos3> {
public static function getHeading():Null<Pos3> {
return heading;
}
public function align(): Promise<Noise> {
public static function align(): Promise<Noise> {
Log.info("Aligning INS");
return new Promise<Noise>((resolve,reject)->{
@@ -94,7 +87,7 @@ class INS {
return null;
}
GPS.instance.locate().handle((pos1)->{
GPS.locate().handle((pos1)->{
Log.debug('pos1: $pos1');
if (pos1 == null) {
Log.warn("GPS not available for 1st position");
@@ -110,7 +103,7 @@ class INS {
return;
}
GPS.instance.locate().handle((pos2)->{
GPS.locate().handle((pos2)->{
Log.debug('pos2: $pos2');
if (pos2 == null) {
Log.warn("GPS not available for 2nd position");
@@ -118,16 +111,16 @@ class INS {
return;
}
var heading = calcHeading(pos1,pos2,moved);
if (heading == null) {
var cHeading = calcHeading(pos1,pos2,moved);
if (cHeading == null) {
Log.error("Can't calculate heading");
reject(new Error("Can't calculate heading"));
return;
}
this.heading = heading;
heading = cHeading;
moveBack(moved);
GPS.instance.setINSPosition(pos1);
GPS.setINSPosition(pos1);
resolve(Noise);
});
@@ -138,7 +131,7 @@ class INS {
}
// -1 = not moved, 0 = back, 1 = forward, 2 = left, 3 = right
private function tryMoving():Int {
private static function tryMoving():Int {
if (Turtle.instance.back().isSuccess()) {
return 0;
} else if (Turtle.instance.forward().isSuccess()) {
@@ -156,7 +149,7 @@ class INS {
}
}
private function calcHeading(pos1: Pos3,pos2:Pos3,moved:Int): Null<Pos3> {
private static function calcHeading(pos1: Pos3,pos2:Pos3,moved:Int): Null<Pos3> {
if (moved == 0) {
return pos1 - pos2;
} else if (moved == 1) {
@@ -170,7 +163,7 @@ class INS {
}
}
private function moveBack(moved:Int) {
private static function moveBack(moved:Int) {
if (moved == 0) {
Turtle.instance.forward();
// cc.Turtle.forward();
@@ -190,7 +183,7 @@ class INS {
}
}
private function rotatePos3ToRight(pos:Pos3):Pos3 {
private static function rotatePos3ToRight(pos:Pos3):Pos3 {
if (pos.x == 0 && pos.z == -1) {
return {x: 1, y: 0, z: 0};
} else if (pos.x == -1 && pos.z == 0) {
@@ -204,7 +197,7 @@ class INS {
}
}
private function rotatePos3ToLeft(pos3:Pos3):Pos3 {
private static function rotatePos3ToLeft(pos3:Pos3):Pos3 {
return rotatePos3ToRight(rotatePos3ToRight(rotatePos3ToRight(pos3)));
}

View File

@@ -8,13 +8,13 @@ using tink.CoreApi;
class Http {
public static function request(url:String,?body:String,?options: String):Future<Outcome<HTTPResponse,HTTPFailure>> {
return new Future<Outcome<HTTPResponse,HTTPFailure>>((resolve) -> {
KernelEvents.instance.onHttpFailure.handle((params)->{
KernelEvents.onHttpFailure.handle((params)->{
if (params.url == url){
resolve(Failure(new HTTPFailure(params.failReason,params.handle)));
}
});
KernelEvents.instance.onHttpSuccess.handle((params) -> {
KernelEvents.onHttpSuccess.handle((params) -> {
if (params.url == url){
resolve(Success(new HTTPResponse(params.handle)));
}

View File

@@ -11,42 +11,41 @@ using tink.CoreApi;
Central logging system.
**/
class Log {
public static var instance:Log;
private static inline final MAX_LINES:Int = 100;
public final onLog:Signal<LogLine>;
public static var onLog(default, null):Signal<LogLine>;
private final onLogTrigger:SignalTrigger<LogLine> = new SignalTrigger();
private final logLines:Array<LogLine> = [];
private static final onLogTrigger:SignalTrigger<LogLine> = new SignalTrigger();
private static final logLines:Array<LogLine> = [];
public function new() {
@:allow(kernel.Init)
private static function init() {
onLog = onLogTrigger.asSignal();
}
public static function info(msg:Dynamic, ?pos:haxe.PosInfos) {
instance.log({level: Info, message: Std.string(msg),time: 0},pos);
log({level: Info, message: Std.string(msg),time: 0},pos);
}
public static function warn(msg:Dynamic, ?pos:haxe.PosInfos) {
instance.log({level: Warn, message: Std.string(msg),time: 0},pos);
log({level: Warn, message: Std.string(msg),time: 0},pos);
}
public static function error(msg:Dynamic, ?pos:haxe.PosInfos) {
instance.log({level: Error, message: Std.string(msg),time: 0},pos);
log({level: Error, message: Std.string(msg),time: 0},pos);
}
public static function debug(msg:Dynamic, ?pos:haxe.PosInfos) {
#if debug
instance.log({level: Debug, message: Std.string(msg),time: 0},pos);
log({level: Debug, message: Std.string(msg),time: 0},pos);
#end
}
public static function silly(msg:Dynamic, ?pos:haxe.PosInfos) {
instance.log({level: Silly, message: Std.string(msg),time: 0},pos);
log({level: Silly, message: Std.string(msg),time: 0},pos);
}
private function log(line: LogLine, ?pos:haxe.PosInfos) {
private static function log(line: LogLine, ?pos:haxe.PosInfos) {
line.origin = pos.className;
logLines.push(line);
@@ -60,7 +59,7 @@ class Log {
#end
}
public function getLines():ReadOnlyArray<LogLine> {
public static function getLines():ReadOnlyArray<LogLine> {
return logLines;
}
}

View File

@@ -20,33 +20,34 @@ class Net {
/**
Depends on: KernelEvents
**/
public static var instance:Net;
public static inline final BRODCAST_PORT:Int = 65533;
public static inline final MESSAGE_TIMEOUT:Int = 3;
public static inline final DEFAULT_TTL:Int = 10;
public final networkID:NetworkID = OS.getComputerID();
private final responseBus:Map<Int, Callback<Outcome<GenericPackage,Error>>> = new Map();
private final protoHandlers:Map<String, Callback<GenericPackage>> = new Map();
private var interfaces:Array<INetworkInterface>;
public static final networkID:NetworkID = OS.getComputerID();
private static final responseBus:Map<Int, Callback<Outcome<GenericPackage,Error>>> = new Map();
private static final protoHandlers:Map<String, Callback<GenericPackage>> = new Map();
private static var interfaces:Array<INetworkInterface>;
@:allow(kernel.Init)
private function new() {
this.interfaces = [for (e in Peripheral.instance.getAllModems()) e ]; // TODO: is this the way to do it?
this.interfaces.push(Loopback.instance);
private static function init() {
interfaces = [for (e in Peripheral.getAllModems()) e ]; // TODO: is this the way to do it?
interfaces.push(Loopback.instance);
for (interf in interfaces){
setupInterf(interf);
}
setupPingHandle();
Routing.setup();
}
private function setupPingHandle() {
this.registerProto("icmp", pack -> {
private static function setupPingHandle() {
registerProto("icmp", pack -> {
switch pack.data.type {
case "ping":
this.respondTo(pack, "pong");
respondTo(pack, "pong");
case "died":
// If we get a "died" message from a node when one of our packages ttl hits 0
// the `data.msgId` prop is the message id
@@ -60,7 +61,7 @@ class Net {
});
}
private function setupInterf(interf: INetworkInterface) {
private static function setupInterf(interf: INetworkInterface) {
interf.onMessage.handle(e -> handle(e.pack,interf,e.dist));
interf.listen(networkID);
interf.listen(BRODCAST_PORT);
@@ -69,8 +70,8 @@ class Net {
/**
Called when a new package comes in.
**/
private function handle(pack:GenericPackage,interf: INetworkInterface, ?dist: Float) {
if (pack.toID == this.networkID || pack.toID == Net.BRODCAST_PORT){
private static function handle(pack:GenericPackage,interf: INetworkInterface, ?dist: Float) {
if (pack.toID == networkID || pack.toID == Net.BRODCAST_PORT){
switch pack.type {
case Data(_) | DataNoResponse(_):
// Let a local proccess handle it
@@ -82,14 +83,14 @@ class Net {
}
case RouteDiscover(_) | RouteDiscoverResponse(_) | RouteDiscoverUpdate(_):
// Delegate to Routing
Routing.instance.handleRoutePackage(cast pack,interf);
Routing.handleRoutePackage(cast pack,interf);
case GPSRequest | GPSResponse(_):
if (dist == null) {
Log.silly("Got a GPS package but no distance was provided");
return;
}
// Delegate to GPS
GPS.instance.handlePackage(cast pack,dist,interf);
GPS.handlePackage(cast pack,dist,interf);
}
}else{
// New message received but its not ment for us. Forward if possible.
@@ -97,14 +98,14 @@ class Net {
}
}
private function generateMessageID():Int {
private static function generateMessageID():Int {
return Std.random(2147483647); // TODO: better uniqe number
}
/**
Send a message. Dont care if its reaches its destination nor it has a response.
**/
public function sendAndForget(dest:Int, proto:String, data:Dynamic) {
public static function sendAndForget(dest:Int, proto:String, data:Dynamic) {
var pack:GenericPackage = {
toID: dest,
fromID: networkID,
@@ -117,7 +118,7 @@ class Net {
sendRaw(pack);
}
private function forwardPackage(pack: GenericPackage) {
private static function forwardPackage(pack: GenericPackage) {
if (pack.ttl == 0){
if (pack.type.match(Data(_))) {
@@ -137,7 +138,7 @@ class Net {
}
}
public function respondTo(pack:GenericPackage, data:Dynamic) {
public static function respondTo(pack:GenericPackage, data:Dynamic) {
if (pack.type.match(DataNoResponse(_))) {
Log.warn("Responed to a no response package. Ignoring");
return;
@@ -151,7 +152,7 @@ class Net {
/**
Send to package to the localy register handler based on the proto
**/
private function routeToProto(pack:GenericPackage) {
private static function routeToProto(pack:GenericPackage) {
var proto = switch pack.type {
case Data(proto):
proto;
@@ -173,20 +174,20 @@ class Net {
Just send the package to the right modem.
Returns true if message was send
**/
private function sendRaw(pack:GenericPackage): Bool {
var route = Routing.instance.getRouteToID(pack.toID);
private static function sendRaw(pack:GenericPackage): Bool {
var route = Routing.getRouteToID(pack.toID);
if (route == null){
return false;
}
route.interf.send(route.rep,this.networkID,pack);
route.interf.send(route.rep,networkID,pack);
return true;
}
/**
Send a message and wait for a response.
**/
public function sendAndAwait<T>(dest:NetworkID, proto:String, data:T):Promise<GenericPackage> {
public static function sendAndAwait<T>(dest:NetworkID, proto:String, data:T):Promise<GenericPackage> {
return new Promise<GenericPackage>((resolve, reject) -> {
var pack:GenericPackage = {
toID: dest,
@@ -228,7 +229,7 @@ class Net {
});
}
public function registerProto(proto:String, callback:Callback<GenericPackage>) {
public static function registerProto(proto:String, callback:Callback<GenericPackage>) {
if (protoHandlers.exists(proto)) {
// Failed. Handler already exist.
// TODO: return error
@@ -238,16 +239,16 @@ class Net {
protoHandlers[proto] = callback;
}
public function removeProto(proto:String) {
public static function removeProto(proto:String) {
protoHandlers.remove(proto);
}
/**
Sends a ping package to the given id. Returns true if there was a response.
**/
public function ping(toID: NetworkID): Promise<Noise> {
public static function ping(toID: NetworkID): Promise<Noise> {
return new Promise<Noise>((resolve,reject)->{
this.sendAndAwait(toID,"icmp",{type:"ping"}).handle(pack -> {
sendAndAwait(toID,"icmp",{type:"ping"}).handle(pack -> {
switch pack {
case Success(_):
resolve(Noise);
@@ -259,7 +260,7 @@ class Net {
});
}
public function getActiveProtocols(): ReadOnlyArray<String> {
public static function getActiveProtocols(): ReadOnlyArray<String> {
var arr = new Array<String>();
for (proto in protoHandlers.keys()) {
@@ -270,7 +271,7 @@ class Net {
}
@:allow(kernel.gps.GPS)
private function brodcastGPSRequest() {
private static function brodcastGPSRequest() {
var pack: Package<Noise> = {
fromID: networkID,
toID: Net.BRODCAST_PORT,
@@ -280,9 +281,9 @@ class Net {
data: null,
};
for (modem in Peripheral.instance.getAllModems()) {
for (modem in Peripheral.getAllModems()) {
if (!modem.isWireless()) continue;
modem.send(Net.BRODCAST_PORT, Net.instance.networkID, pack);
modem.send(Net.BRODCAST_PORT, networkID, pack);
}
}
}

View File

@@ -51,9 +51,9 @@ enum PackageTypes {
}
/**
Wrapper for `Net.instance.respondTo`.
Wrapper for `Net.respondTo`.
**/
public function respond(data:Dynamic) {
Net.instance.respondTo(this, data);
Net.respondTo(this, data);
}
}

View File

@@ -20,24 +20,23 @@ class Routing {
/**
Depends on: Peripheral
**/
public static var instance:Routing;
public static inline final UPDATE_WAIT_TIME:Float = 1;
public final onNewNeigbor:Signal<Int>;
public static var onNewNeigbor(default, null):Signal<Int>;
private final onNewNeigborTrigger:SignalTrigger<NetworkID> = Signal.trigger();
private final routingTable:Map<NetworkID, Route> = new Map();
private var routeUpdateInQueue:Bool = false;
private static final onNewNeigborTrigger:SignalTrigger<NetworkID> = Signal.trigger();
private static final routingTable:Map<NetworkID, Route> = new Map();
private static var routeUpdateInQueue:Bool = false;
@:allow(kernel.Init)
private function new() {
this.onNewNeigbor = this.onNewNeigborTrigger.asSignal();
private static function init() {
onNewNeigbor = onNewNeigborTrigger.asSignal();
}
@:allow(kernel.Init)
private function init() {
routingTable.set(Net.instance.networkID, {interf: Loopback.instance, cost: 0, rep: Net.instance.networkID});
@:allow(kernel.net.Net)
private static function setup() {
routingTable.set(Net.networkID, {interf: Loopback.instance, cost: 0, rep: Net.networkID});
brodcastRoutingTable();
}
@@ -45,27 +44,27 @@ class Routing {
Prepares an brodcast of the current routing table. If a brodcast is already in queue it will be ignored.
After UPDATE_WAIT_TIME seconds the routing table will be brodcasted. This is done to prevent spamming the network.
**/
private function prepareRouteUpdate() {
if (this.routeUpdateInQueue) {
private static function prepareRouteUpdate() {
if (routeUpdateInQueue) {
return;
}
this.routeUpdateInQueue = true;
routeUpdateInQueue = true;
new Timer(UPDATE_WAIT_TIME, () -> {
brodcastRoutingTable();
this.routeUpdateInQueue = false;
routeUpdateInQueue = false;
});
}
/**
Brodcast the current routing table to all peers.
**/
private function brodcastRoutingTable() {
private static function brodcastRoutingTable() {
var pack = newRoutDiscoverPackage();
for (modem in Peripheral.instance.getAllModems()) {
modem.send(Net.BRODCAST_PORT, Net.instance.networkID, pack);
for (modem in Peripheral.getAllModems()) {
modem.send(Net.BRODCAST_PORT, Net.networkID, pack);
}
}
@@ -73,7 +72,7 @@ class Routing {
Handle incomming packages that involve route discovery.
**/
@:allow(kernel.net.Net)
private function handleRoutePackage(pack:Package<Noise>, interf:INetworkInterface):Void {
private static function handleRoutePackage(pack:Package<Noise>, interf:INetworkInterface):Void {
addPossibleRoute(pack.fromID, interf, 0, pack.fromID);
var shouldRespond:Bool = switch pack.type {
@@ -104,22 +103,22 @@ class Routing {
// Respond to peer
var response:Package<Noise> = {
toID: pack.fromID,
fromID: Net.instance.networkID,
fromID: Net.networkID,
msgID: null,
type: RouteDiscoverResponse(genRouteList()),
data: null,
ttl: 0, // Prevent forwarding
}
interf.send(response.toID, Net.instance.networkID, response);
interf.send(response.toID, Net.networkID, response);
}
/**
Generate a list of routes to send to a peer based on the current routing table.
**/
private function genRouteList():Array<{id:NetworkID, cost:Int}> {
private static function genRouteList():Array<{id:NetworkID, cost:Int}> {
var routes:Array<{id:NetworkID, cost:Int}> = [];
for (k => v in this.routingTable) {
for (k => v in routingTable) {
routes.push({
id: k,
cost: v.cost
@@ -128,12 +127,12 @@ class Routing {
return routes;
}
private function newRoutDiscoverPackage():Package<Noise> {
private static function newRoutDiscoverPackage():Package<Noise> {
var pack:Package<Noise> = {
type: RouteDiscover(genRouteList()),
toID: Net.BRODCAST_PORT,
msgID: null,
fromID: Net.instance.networkID,
fromID: Net.networkID,
data: null,
ttl: 0, // Prevent forwarding
}
@@ -145,31 +144,31 @@ class Routing {
Called when a route to a client has been disoverd.
Its possible to be called multiple times with the same id but different addr.
**/
private function addPossibleRoute(toID:Int, interf:INetworkInterface, cost:Int, rep:NetworkID) {
if (toID == Net.instance.networkID) {
private static function addPossibleRoute(toID:Int, interf:INetworkInterface, cost:Int, rep:NetworkID) {
if (toID == Net.networkID) {
return;
}
var fullCost = cost + interf.getBaseRoutingCost();
if (this.routingTable.exists(toID)) {
if (this.routingTable[toID].cost > fullCost) {
this.routingTable[toID] = {interf: interf, cost: cost + interf.getBaseRoutingCost(), rep: rep};
this.prepareRouteUpdate();
if (routingTable.exists(toID)) {
if (routingTable[toID].cost > fullCost) {
routingTable[toID] = {interf: interf, cost: cost + interf.getBaseRoutingCost(), rep: rep};
prepareRouteUpdate();
}
} else {
this.routingTable[toID] = {interf: interf, cost: cost + interf.getBaseRoutingCost(), rep: rep};
this.onNewNeigborTrigger.trigger(toID);
this.prepareRouteUpdate();
routingTable[toID] = {interf: interf, cost: cost + interf.getBaseRoutingCost(), rep: rep};
onNewNeigborTrigger.trigger(toID);
prepareRouteUpdate();
}
}
public function getRouteToID(networkID:NetworkID):{interf:INetworkInterface, rep:NetworkID} {
if (networkID == Net.instance.networkID) {
return {interf: Loopback.instance, rep: Net.instance.networkID};
public static function getRouteToID(networkID:NetworkID):{interf:INetworkInterface, rep:NetworkID} {
if (networkID == Net.networkID) {
return {interf: Loopback.instance, rep: Net.networkID};
}
var route:Null<Route> = this.routingTable[networkID];
var route:Null<Route> = routingTable[networkID];
if (route == null) {
return null;
@@ -178,7 +177,7 @@ class Routing {
}
}
public function getRouteTable():Map<NetworkID, Route> {
return this.routingTable;
public static function getRouteTable():Map<NetworkID, Route> {
return routingTable;
}
}

View File

@@ -22,13 +22,13 @@ class Drive implements IPeripheral {
this.onDiskInsert = this.onDiskInsertTrigger.asSignal();
this.onDiskEject = this.onDiskEjectTrigger.asSignal();
KernelEvents.instance.onDisk.handle((addr) ->{
KernelEvents.onDisk.handle((addr) ->{
if (addr == this.addr){
this.onDiskInsertTrigger.trigger(null);
}
});
KernelEvents.instance.onDiskEject.handle((addr)->{
KernelEvents.onDiskEject.handle((addr)->{
if (addr == this.addr){
this.onDiskEjectTrigger.trigger(null);
}

View File

@@ -22,7 +22,7 @@ class Modem implements INetworkInterface implements IPeripheral {
this.native = Peripheral.wrap(addr);
this.addr = addr;
KernelEvents.instance.onModemMessage.handle(params ->{
KernelEvents.onModemMessage.handle(params ->{
try{
if (params.addr == this.addr){
var pack:GenericPackage = {

View File

@@ -11,24 +11,15 @@ using tink.CoreApi;
Class responseable for retrieving peripherals.
**/
class Peripheral {
/**
Depends on: KernelEvents
**/
public static var instance:Peripheral;
@:allow(kernel.Init)
private function new() {
}
public function getAllAddresses(): Array<String> {
public static function getAllAddresses(): Array<String> {
return cc.Peripheral.getNames().toArray();
}
public function isPresent(addr: String): Bool {
public static function isPresent(addr: String): Bool {
return cc.Peripheral.isPresent(addr);
}
public function getTypes(addr: String): Array<String> {
public static function getTypes(addr: String): Array<String> {
if (!cc.Peripheral.isPresent(addr)) {
return [];
}
@@ -36,11 +27,11 @@ class Peripheral {
return cc.Peripheral.getType(addr).toArray();
}
public function findAddrByType(type: String): Array<String> {
public static function findAddrByType(type: String): Array<String> {
return getAllAddresses().filter(addr -> getTypes(addr).contains(type));
}
private function safeGetAddr(addr: String, type: String): Null<String> {
private static function safeGetAddr(addr: String, type: String): Null<String> {
if (!isPresent(addr)) {
return null;
}
@@ -53,7 +44,7 @@ class Peripheral {
return addr;
}
public function inspect(addr: String): Null<{ types: Array<String>, methods: Array<String>}> {
public static function inspect(addr: String): Null<{ types: Array<String>, methods: Array<String>}> {
if (!isPresent(addr)) {
return null;
}
@@ -76,7 +67,7 @@ class Peripheral {
Cast peripheral to a specific type.
This is a temporary solution, maybe forever.
**/
public function getFromType(addr: String, type: String): Null<IPeripheral> {
public static function getFromType(addr: String, type: String): Null<IPeripheral> {
switch (type){
case Computer.TYPE_NAME:
return getComputer(addr);
@@ -97,69 +88,69 @@ class Peripheral {
return null;
}
public function getScreen(addr: String): Null<Screen> {
public static function getScreen(addr: String): Null<Screen> {
var addr = safeGetAddr(addr, Screen.TYPE_NAME);
if (addr == null) return null;
return new Screen(addr);
}
public function getAllScreens(): Array<Screen> {
public static function getAllScreens(): Array<Screen> {
return [ for (addr in findAddrByType(Screen.TYPE_NAME)) new Screen(addr)];
}
public function getModem(addr: String): Null<Modem> {
public static function getModem(addr: String): Null<Modem> {
var addr = safeGetAddr(addr, Modem.TYPE_NAME);
if (addr == null) return null;
return new Modem(addr);
}
public function getAllModems(): Array<Modem> {
public static function getAllModems(): Array<Modem> {
return [ for (addr in findAddrByType(Modem.TYPE_NAME)) new Modem(addr)];
}
public function getDrive(addr: String): Null<Drive> {
public static function getDrive(addr: String): Null<Drive> {
var addr = safeGetAddr(addr, Drive.TYPE_NAME);
if (addr == null) return null;
return new Drive(addr);
}
public function getAllDrives(): Array<Drive> {
public static function getAllDrives(): Array<Drive> {
return [ for (addr in findAddrByType(Drive.TYPE_NAME)) new Drive(addr)];
}
public function getRedstone(side: String): Redstone {
public static function getRedstone(side: String): Redstone {
// TODO: maybe handle restone differently to not duplicate event listeners
return new Redstone(side);
}
public function getPrinter(addr: String):Null<Printer> {
public static function getPrinter(addr: String):Null<Printer> {
var addr = safeGetAddr(addr, Printer.TYPE_NAME);
if (addr == null) return null;
return new Printer(addr);
}
public function getAllPrinters(): Array<Printer> {
public static function getAllPrinters(): Array<Printer> {
return [ for (addr in findAddrByType(Printer.TYPE_NAME)) new Printer(addr)];
}
public function getEnergyStorage(addr: String): Null<EnergyStorage> {
public static function getEnergyStorage(addr: String): Null<EnergyStorage> {
var addr = safeGetAddr(addr, EnergyStorage.TYPE_NAME);
if (addr == null) return null;
return new EnergyStorage(addr);
}
public function getAllEnergyStorages(): Array<EnergyStorage> {
public static function getAllEnergyStorages(): Array<EnergyStorage> {
return [ for (addr in findAddrByType(EnergyStorage.TYPE_NAME)) new EnergyStorage(addr)];
}
public function getComputer(addr: String): Null<Computer> {
public static function getComputer(addr: String): Null<Computer> {
var addr = safeGetAddr(addr, Computer.TYPE_NAME);
if (addr == null) return null;
return new Computer(addr);
}
public function getAllComputers(): Array<Computer> {
public static function getAllComputers(): Array<Computer> {
return [ for (addr in findAddrByType(Computer.TYPE_NAME)) new Computer(addr)];
}
}

View File

@@ -63,7 +63,7 @@ class Redstone implements IPeripheral implements IExportable {
updateState();
KernelEvents.instance.onRedstone.handle(()->{
KernelEvents.onRedstone.handle(()->{
if ((this.getAnalogInput() != this.analogInputState) || (this.bundleInputState != this.getBundledInput())){
updateState();
this.onChangeTrigger.trigger(null);

View File

@@ -26,7 +26,7 @@ class Screen implements TermWriteable implements IPeripheral {
this.nativ = Peripheral.wrap(addr);
this.addr = addr;
KernelEvents.instance.onMonitorResize.handle(addr -> {
KernelEvents.onMonitorResize.handle(addr -> {
if (addr == this.addr) {
onResizeTrigger.trigger(getSize());
}

View File

@@ -63,13 +63,13 @@ class ProcessHandle {
}
public function createBufferdWindowContext(): WindowContext {
var ctx = WindowManager.instance.createNewContext();
var ctx = WindowManager.createNewContext();
this.windowContexts.push(ctx);
return ctx;
}
public function createStatelessWindowContext(): {ctx:WindowContext, setRenderFunc: (() -> Void) -> Void, requestRender:() -> Void} {
var ctx = WindowManager.instance.createNewStatelessContext();
var ctx = WindowManager.createNewStatelessContext();
this.windowContexts.push(ctx.ctx);
return ctx;
}

View File

@@ -21,7 +21,7 @@ class Service {
}
public function start() {
var bin = BinStore.instance.getBinByAlias(this.binName);
var bin = BinStore.getBinByAlias(this.binName);
if (bin == null){
throw new Error('Bin ${this.binName} not found');

View File

@@ -7,20 +7,18 @@ import lib.KVStore;
using tink.CoreApi;
class ServiceManager {
public static var instance: ServiceManager;
private final services:Map<String,Service> = new Map();
private static final services:Map<String,Service> = new Map();
@:allow(kernel.Init)
private function new() {
this.startAllEnabled();
private static function init() {
startAllEnabled();
}
/**
Add a service to be automatically started.
**/
public function enable(name: String) {
if (!this.services.exists(name)){
public static function enable(name: String) {
if (!services.exists(name)){
return; // Service must be started
}
@@ -36,7 +34,7 @@ class ServiceManager {
/**
Remove a service from being automatically started.
**/
private function disable(name: String) {
private static function disable(name: String) {
var store = KVStore.getStoreForClass();
var enabled: Array<String> = store.get("enabled");
var index = enabled.indexOf(name);
@@ -48,15 +46,15 @@ class ServiceManager {
store.save();
}
private function startAllEnabled() {
private static function startAllEnabled() {
var store = KVStore.getStoreForClass();
var enabled: Array<String> = store.get("enabled",[]);
for (name in enabled){
this.start(name);
start(name);
}
}
private function load(name: String): Null<Service> {
private static function load(name: String): Null<Service> {
var store = new KVStore('service/${name}');
store.load();
if (!store.exists("service")){
@@ -66,12 +64,12 @@ class ServiceManager {
return store.get("service");
}
public function register(name: String, binName: String,args: Array<String>): Outcome<Noise,String> {
if (BinStore.instance.getBinByAlias(binName) == null){
public static function register(name: String, binName: String,args: Array<String>): Outcome<Noise,String> {
if (BinStore.getBinByAlias(binName) == null){
return Failure("bin not found");
}
if (this.load(name) != null){
if (load(name) != null){
return Failure("service already exists");
}
@@ -85,8 +83,8 @@ class ServiceManager {
return Success(Noise);
}
public function unregister(name: String): Outcome<Noise,String> {
if (this.services.exists(name)){
public static function unregister(name: String): Outcome<Noise,String> {
if (services.exists(name)){
return Failure("service is running");
}
@@ -95,48 +93,48 @@ class ServiceManager {
return Success(Noise);
}
public function start(name: String): Outcome<Noise,String> {
var service = this.load(name);
public static function start(name: String): Outcome<Noise,String> {
var service = load(name);
if (service == null){
return Failure("service not found");
}
service.start();
this.services.set(name,service);
services.set(name,service);
Log.info('Service ${name} started');
return Success(Noise);
}
public function stop(name: String): Outcome<Noise,String> {
if (!this.services.exists(name)){
public static function stop(name: String): Outcome<Noise,String> {
if (!services.exists(name)){
return Failure("service not found");
}
var service = this.services.get(name);
var service = services.get(name);
service.stop();
this.services.remove(name);
services.remove(name);
Log.info('Service ${name} stopped');
return Success(Noise);
}
public function listRunning(): Array<String> {
public static function listRunning(): Array<String> {
var running = [];
for (name in this.services.keys()){
for (name in services.keys()){
running.push(name);
}
return running;
}
public function get(name: String): Null<Dynamic> {
if (!this.services.exists(name)){
public static function get(name: String): Null<Dynamic> {
if (!services.exists(name)){
return null;
}
// TODO: Maybe there is a way to check types here?
var srv = this.services.get(name);
var srv = services.get(name);
return srv.ps;
}

View File

@@ -36,42 +36,42 @@ class Turtle {
public function forward():Outcome<Noise, String> {
var r = cc.Turtle.forward();
var r2 = conterToOutcome(r);
if (r2.isSuccess()) INS.instance.moveForward();
if (r2.isSuccess()) INS.moveForward();
return r2;
}
public function back():Outcome<Noise, String> {
var r = cc.Turtle.back();
var r2 = conterToOutcome(r);
if (r2.isSuccess()) INS.instance.moveBackward();
if (r2.isSuccess()) INS.moveBackward();
return r2;
}
public function up():Outcome<Noise, String> {
var r = cc.Turtle.up();
var r2 = conterToOutcome(r);
if (r2.isSuccess()) INS.instance.moveUp();
if (r2.isSuccess()) INS.moveUp();
return r2;
}
public function down():Outcome<Noise, String> {
var r = cc.Turtle.down();
var r2 = conterToOutcome(r);
if (r2.isSuccess()) INS.instance.moveDown();
if (r2.isSuccess()) INS.moveDown();
return r2;
}
public function turnLeft():Outcome<Noise, String> {
var r = cc.Turtle.turnLeft();
var r2 = conterToOutcome(r);
if (r2.isSuccess()) INS.instance.turnRight();
if (r2.isSuccess()) INS.turnRight();
return r2;
}
public function turnRight():Outcome<Noise, String> {
var r = cc.Turtle.turnRight();
var r2 = conterToOutcome(r);
if (r2.isSuccess()) INS.instance.turnRight();
if (r2.isSuccess()) INS.turnRight();
return r2;
}

View File

@@ -14,13 +14,12 @@ class WindowManager {
/**
Depends on: KernelEvents, Peripheral
**/
public static var instance:WindowManager;
private var currentMainContext:WindowContext;
private final outputMap:Map<String, WindowContext> = new Map();
private static var currentMainContext:WindowContext;
private static final outputMap:Map<String, WindowContext> = new Map();
@:allow(kernel.Init)
private function new() {
KernelEvents.instance.onKey.handle(params -> {
private static function init() {
KernelEvents.onKey.handle(params -> {
if (currentMainContext != null) {
if (currentMainContext.eventDelegate != null){
var foo = currentMainContext.eventDelegate.getEventHandlers();
@@ -31,7 +30,7 @@ class WindowManager {
}
});
KernelEvents.instance.onKeyUp.handle(keyCode -> {
KernelEvents.onKeyUp.handle(keyCode -> {
if (currentMainContext != null) {
if (currentMainContext.eventDelegate != null){
var foo = currentMainContext.eventDelegate.getEventHandlers();
@@ -42,7 +41,7 @@ class WindowManager {
}
});
KernelEvents.instance.onMouseClick.handle(params -> {
KernelEvents.onMouseClick.handle(params -> {
if (currentMainContext != null) {
if (currentMainContext.eventDelegate != null){
var foo = currentMainContext.eventDelegate.getEventHandlers();
@@ -53,7 +52,7 @@ class WindowManager {
}
});
KernelEvents.instance.onMouseDrag.handle(params -> {
KernelEvents.onMouseDrag.handle(params -> {
if (currentMainContext != null) {
if (currentMainContext.eventDelegate != null){
var foo = currentMainContext.eventDelegate.getEventHandlers();
@@ -64,7 +63,7 @@ class WindowManager {
}
});
KernelEvents.instance.onMouseScroll.handle(params -> {
KernelEvents.onMouseScroll.handle(params -> {
if (currentMainContext != null) {
if (currentMainContext.eventDelegate != null){
var foo = currentMainContext.eventDelegate.getEventHandlers();
@@ -75,7 +74,7 @@ class WindowManager {
}
});
KernelEvents.instance.onMouseUp.handle(params -> {
KernelEvents.onMouseUp.handle(params -> {
if (currentMainContext != null) {
if (currentMainContext.eventDelegate != null){
var foo = currentMainContext.eventDelegate.getEventHandlers();
@@ -86,7 +85,7 @@ class WindowManager {
}
});
KernelEvents.instance.onPaste.handle(text -> {
KernelEvents.onPaste.handle(text -> {
if (currentMainContext != null) {
if (currentMainContext.eventDelegate != null){
var foo = currentMainContext.eventDelegate.getEventHandlers();
@@ -97,11 +96,11 @@ class WindowManager {
}
});
KernelEvents.instance.onMonitorTouch.handle(params -> {
KernelEvents.onMonitorTouch.handle(params -> {
// TODO
});
KernelEvents.instance.onChar.handle(char -> {
KernelEvents.onChar.handle(char -> {
if (currentMainContext != null) {
if (currentMainContext.eventDelegate != null){
var foo = currentMainContext.eventDelegate.getEventHandlers();
@@ -116,25 +115,25 @@ class WindowManager {
/**
Same as createNewBufferedContext because it is the most simple context.
**/
public function createNewContext():WindowContext {
public static function createNewContext():WindowContext {
return createNewBufferedContext();
}
public function createNewBufferedContext():WindowContext {
public static function createNewBufferedContext():WindowContext {
var newContext = new WindowContext(new BufferedVirtualTermWriter());
return newContext;
}
public function createNewStatelessContext():{ctx:WindowContext, setRenderFunc:(() -> Void) -> Void, requestRender:Void->Void} {
public static function createNewStatelessContext():{ctx:WindowContext, setRenderFunc:(() -> Void) -> Void, requestRender:Void->Void} {
var writer = new StatelessVirtualTermWriter();
var newContext = new WindowContext(writer);
return {ctx: newContext, setRenderFunc: writer.setRenderFunc, requestRender: writer.requestRender};
}
public function getOutputs():ReadOnlyArray<String> {
var arr = Peripheral.instance.getAllScreens().map(screen -> return screen.getAddr());
public static function getOutputs():ReadOnlyArray<String> {
var arr = Peripheral.getAllScreens().map(screen -> return screen.getAddr());
arr.push("main");
return arr;
}
@@ -142,13 +141,13 @@ class WindowManager {
/**
Move context to output. If output is "main", context will be moved to main screen.
**/
public function focusContextToOutput(context:WindowContext, output:String) {
public static function focusContextToOutput(context:WindowContext, output:String) {
var target:TermWriteable;
if (output == "main") {
target = MainTerm.instance;
currentMainContext = context;
} else {
target = Peripheral.instance.getScreen(output);
target = Peripheral.getScreen(output);
if (target == null) {
// output target not found
@@ -165,7 +164,7 @@ class WindowManager {
context.enable();
}
public function getContextByPID(pid: PID): ReadOnlyArray<WindowContext> {
public static function getContextByPID(pid: PID): ReadOnlyArray<WindowContext> {
var handle = ProcessManager.getProcess(pid);
if (handle == null) {
return [];

View File

@@ -39,13 +39,13 @@ class Debug {
#if Debug
public static function printKernelEventsCount(){
KernelEvents.instance.printListenerCount();
KernelEvents.printListenerCount();
}
#end
#if webconsole
public static function printWeb(msg:String) {
HTTP.request("http://127.0.0.1:8080/"+Net.instance.networkID,msg);
HTTP.request("http://127.0.0.1:8080/"+Net.networkID,msg);
}
#end
}

View File

@@ -41,10 +41,10 @@ class HomeContext {
public function run() {
// Create main terminal context
var stateless = WindowManager.instance.createNewStatelessContext();
var stateless = WindowManager.createNewStatelessContext();
ctx = stateless.ctx;
requestRender = stateless.requestRender;
WindowManager.instance.focusContextToOutput(ctx, "main");
WindowManager.focusContextToOutput(ctx, "main");
renderer = new RootElement();
renderer.setTitle("Home");
@@ -54,7 +54,7 @@ class HomeContext {
requestRender();
// Register global key bindings to react to main terminal
KernelEvents.instance.onKey.handle(e -> {
KernelEvents.onKey.handle(e -> {
// Is HOME pressed?
// TODO: remove magic number
if (e.keyCode == 268) {
@@ -85,14 +85,14 @@ class HomeContext {
private function focusContext(id:Int) {
if (workspaces.exists(id)) {
WindowManager.instance.focusContextToOutput(workspaces[id], selectedOutput);
WindowManager.focusContextToOutput(workspaces[id], selectedOutput);
currentWorkspace = id;
}
}
private function focusMainTerm() {
requestRender();
WindowManager.instance.focusContextToOutput(ctx, "main");
WindowManager.focusContextToOutput(ctx, "main");
currentWorkspace = -1;
}
@@ -105,7 +105,7 @@ class HomeContext {
}
private function spawnPs(binName: String) {
var bin = BinStore.instance.getBinByAlias(binName);
var bin = BinStore.getBinByAlias(binName);
if (bin == null) {
Log.error('Could not find bin: ${binName}');
@@ -116,7 +116,7 @@ class HomeContext {
var pid = ProcessManager.run(ps, {});
var lastContextID = -1;
for ( ctx in WindowManager.instance.getContextByPID(pid)){
for ( ctx in WindowManager.getContextByPID(pid)){
lastContextID = addContextNextWorkspace(ctx);
}
@@ -131,7 +131,7 @@ class HomeContext {
}
private function cycleOutput() {
var screenAddr = Peripheral.instance.findAddrByType(Screen.TYPE_NAME);
var screenAddr = Peripheral.findAddrByType(Screen.TYPE_NAME);
if (selectedOutputIndex == -1) {
selectedOutputIndex = 0;
@@ -159,13 +159,13 @@ class HomeContext {
for (i in 0...listedApps.length) {
children.push(new TextElement(
'Add ${BinStore.instance.getNameByAlias(listedApps[i])}',
'Add ${BinStore.getNameByAlias(listedApps[i])}',
{uiEvents: {onClick: this.spawnPs.bind(listedApps[i])}}
));
}
children.push(new TextElement('Output: ${selectedOutput}',{ uiEvents:{ onClick: this.cycleOutput}}));
children.push(new TextElement('Exit', {style: {bgColor: Red}, uiEvents: {onClick: KernelEvents.instance.shutdown}}));
children.push(new TextElement('Exit', {style: {bgColor: Red}, uiEvents: {onClick: KernelEvents.shutdown}}));
renderer.setChildren(children);

View File

@@ -17,7 +17,7 @@ class RessourceNames {
var payload: GetRequest = {name: name, type: "get"};
return Net.instance.sendAndAwait(
return Net.sendAndAwait(
controllerID,
SiteRessourceController.SITE_CONTROLLER_RESSOURCE_MANAGER_PROTO,
payload
@@ -36,7 +36,7 @@ class RessourceNames {
var payload: RegisterRequest = {name: name, netID: netID, type: "register"};
return Net.instance.sendAndAwait(
return Net.sendAndAwait(
controllerID,
SiteRessourceController.SITE_CONTROLLER_RESSOURCE_MANAGER_PROTO,
payload
@@ -56,7 +56,7 @@ class RessourceNames {
var payload: UnregisterRequest = {name: name, type: "unregister"};
return Net.instance.sendAndAwait(
return Net.sendAndAwait(
controllerID,
SiteRessourceController.SITE_CONTROLLER_RESSOURCE_MANAGER_PROTO,
payload
@@ -68,7 +68,7 @@ class RessourceNames {
var payload: ListRequest = {type: "list"};
return Net.instance.sendAndAwait(
return Net.sendAndAwait(
controllerID,
SiteRessourceController.SITE_CONTROLLER_RESSOURCE_MANAGER_PROTO,
payload

View File

@@ -15,7 +15,7 @@ class Import {
}
private static function performRequest(netID: NetworkID, request: Request): Promise<Response> {
return Net.instance.sendAndAwait(netID,"res",request).map((response)->{
return Net.sendAndAwait(netID,"res",request).map((response)->{
switch (response){
case Success(data):
return Success(cast (data.data, Response));

View File

@@ -71,7 +71,7 @@ class RPC {
}
return macro {
kernel.net.Net.instance.registerProto($v{proto},(pack)->{
kernel.net.Net.registerProto($v{proto},(pack)->{
$a{exprs}
});
};

View File

@@ -14,7 +14,7 @@ abstract class RPCBase {
}
private function _performRequest(func: String, args: Array<Dynamic>):Promise<Dynamic> {
return Net.instance.sendAndAwait(id, this._proto, {
return Net.sendAndAwait(id, this._proto, {
func: func,
// args: args
}).map((res) -> {

21
src/startup.lua Normal file
View File

@@ -0,0 +1,21 @@
-- Check for startup enable flag
if redstone.getInput("top") then
local fd = fs.open("/haxe.lua", "r")
local haxe = fd.readAll()
fd.close()
local make = dofile("rom/modules/main/cc/require.lua").make
local env = {}
env.require, env.package = make(env, "/")
env = setmetatable(env, { __index = _G })
local f,err = load(haxe,"Haxe",nil,env)
if err then
print("Error loading Haxe: " .. err)
else
f()
os.reboot()
end
end