Compare commits
11 Commits
016063e3be
...
a568c9cdd8
| Author | SHA1 | Date | |
|---|---|---|---|
| a568c9cdd8 | |||
| 44772557ba | |||
| 0540cc465a | |||
| 21387cd8e7 | |||
| a46760e587 | |||
| c83f457968 | |||
| b8f5ffb93a | |||
| 3c59e045de | |||
| 4b8bc87db9 | |||
| 0c7280a2f5 | |||
| 98b8465436 |
@@ -8,7 +8,7 @@ set -e
|
||||
# format
|
||||
|
||||
make format
|
||||
|
||||
git diff --name-only --cached | xargs -l git add
|
||||
# build
|
||||
|
||||
make build
|
||||
|
||||
@@ -7,30 +7,38 @@ using tink.CoreApi;
|
||||
class Turtle extends CLIAppBase {
|
||||
public function new() {
|
||||
registerSyncSubcommand("forward", (args) -> {
|
||||
return perform(kernel.turtle.Turtle.instance.forward());
|
||||
return checkAvailable() && perform(kernel.turtle.Turtle.forward());
|
||||
});
|
||||
|
||||
registerSyncSubcommand("back", (args) -> {
|
||||
return perform(kernel.turtle.Turtle.instance.back());
|
||||
return checkAvailable() && perform(kernel.turtle.Turtle.back());
|
||||
});
|
||||
|
||||
registerSyncSubcommand("left", (args) -> {
|
||||
return perform(kernel.turtle.Turtle.instance.turnLeft());
|
||||
return checkAvailable() && perform(kernel.turtle.Turtle.turnLeft());
|
||||
});
|
||||
|
||||
registerSyncSubcommand("right", (args) -> {
|
||||
return perform(kernel.turtle.Turtle.instance.turnRight());
|
||||
return checkAvailable() && perform(kernel.turtle.Turtle.turnRight());
|
||||
});
|
||||
|
||||
registerSyncSubcommand("up", (args) -> {
|
||||
return perform(kernel.turtle.Turtle.instance.up());
|
||||
return checkAvailable() && perform(kernel.turtle.Turtle.up());
|
||||
});
|
||||
|
||||
registerSyncSubcommand("down", (args) -> {
|
||||
return perform(kernel.turtle.Turtle.instance.down());
|
||||
return checkAvailable() && perform(kernel.turtle.Turtle.down());
|
||||
});
|
||||
}
|
||||
|
||||
private function checkAvailable():Bool {
|
||||
if (!kernel.turtle.Turtle.isTurtle()) {
|
||||
handle.write("This is not a turtle!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function perform(outcome:Outcome<Noise, String>):Bool {
|
||||
switch outcome {
|
||||
case Success(_):
|
||||
|
||||
67
src/bin/turtle/Excavate.hx
Normal file
67
src/bin/turtle/Excavate.hx
Normal file
@@ -0,0 +1,67 @@
|
||||
package bin.turtle;
|
||||
|
||||
import lib.turtle.Helper;
|
||||
import lib.turtle.TurtleAppBase;
|
||||
|
||||
class Excavate extends TurtleAppBase {
|
||||
private var x:Int = 0;
|
||||
private var y:Int = 0;
|
||||
private var z:Int = 0;
|
||||
|
||||
public function new() {
|
||||
super(init, turtleFunction);
|
||||
}
|
||||
|
||||
private function init() {
|
||||
if (handle.args.length < 2) {
|
||||
handle.writeLine("Usage: excavate <front> <right> <down>");
|
||||
handle.close(false);
|
||||
}
|
||||
|
||||
var parsedX = Std.parseInt(handle.args[0]);
|
||||
var parsedY = Std.parseInt(handle.args[1]);
|
||||
var parsedZ = Std.parseInt(handle.args[2]);
|
||||
|
||||
if (parsedX == null || parsedY == null || parsedZ == null) {
|
||||
handle.writeLine("Invalid arguments");
|
||||
handle.close(false);
|
||||
}
|
||||
|
||||
this.x = parsedX;
|
||||
this.y = parsedY;
|
||||
this.z = parsedZ;
|
||||
}
|
||||
|
||||
private function turtleFunction() {
|
||||
for (z in 0...this.z) {
|
||||
for (y in 0...this.y) {
|
||||
for (x in 0...this.x) {
|
||||
kernel.turtle.Turtle.dig(Down);
|
||||
|
||||
if (x < this.x - 1) {
|
||||
kernel.turtle.Turtle.forward();
|
||||
}
|
||||
}
|
||||
|
||||
if (y < this.y - 1) {
|
||||
if (y % 2 == 0) {
|
||||
kernel.turtle.Turtle.turnRight();
|
||||
kernel.turtle.Turtle.forward();
|
||||
kernel.turtle.Turtle.turnRight();
|
||||
} else {
|
||||
kernel.turtle.Turtle.turnLeft();
|
||||
kernel.turtle.Turtle.forward();
|
||||
kernel.turtle.Turtle.turnLeft();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kernel.turtle.Turtle.dig(Down);
|
||||
kernel.turtle.Turtle.down();
|
||||
|
||||
Helper.times(kernel.turtle.Turtle.turnLeft, 2);
|
||||
}
|
||||
|
||||
handle.close(true);
|
||||
}
|
||||
}
|
||||
31
src/bin/turtle/Patrol.hx
Normal file
31
src/bin/turtle/Patrol.hx
Normal file
@@ -0,0 +1,31 @@
|
||||
package bin.turtle;
|
||||
|
||||
import kernel.turtle.TurtleMutex;
|
||||
import kernel.ps.ProcessHandle;
|
||||
import kernel.ps.Process;
|
||||
|
||||
class Patrol implements Process {
|
||||
private var handle:ProcessHandle;
|
||||
|
||||
public function new() {}
|
||||
|
||||
public function run(handle:ProcessHandle) {
|
||||
this.handle = handle;
|
||||
|
||||
if (!handle.claimTurtleMutex()) {
|
||||
handle.writeLine("Failed to claim turtle mutex");
|
||||
handle.close();
|
||||
}
|
||||
|
||||
handle.writeLine("Patroling");
|
||||
|
||||
TurtleMutex.runInTThread(() -> {
|
||||
while (true) {
|
||||
kernel.turtle.Turtle.forward();
|
||||
kernel.turtle.Turtle.forward();
|
||||
kernel.turtle.Turtle.forward();
|
||||
kernel.turtle.Turtle.turnLeft();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -16,5 +16,7 @@ class Entrypoint {
|
||||
} catch (e) {
|
||||
Log.error('Error in startup: ${e.toString()}');
|
||||
}
|
||||
|
||||
KernelEvents.startEventLoop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
package kernel;
|
||||
|
||||
import kernel.service.ServiceManager;
|
||||
import kernel.binstore.BinStore;
|
||||
import kernel.gps.INS;
|
||||
import kernel.fs.FS;
|
||||
import kernel.gps.GPS;
|
||||
import kernel.log.Log;
|
||||
import kernel.turtle.Turtle;
|
||||
import haxe.MainLoop;
|
||||
import kernel.net.Routing;
|
||||
import cc.OS;
|
||||
import lib.Debug;
|
||||
import kernel.ui.WindowManager;
|
||||
import kernel.peripherals.Peripherals.Peripheral;
|
||||
import kernel.net.Net;
|
||||
import kernel.DCEHack; // Important for DCE hack
|
||||
|
||||
class Init {
|
||||
@:allow(kernel.KernelEvents)
|
||||
private static var mainEvent:MainEvent;
|
||||
|
||||
public static function initKernel() {
|
||||
// Init singeltons here because haxe is confused about the order to create them.
|
||||
Log.init();
|
||||
@@ -28,10 +20,6 @@ class Init {
|
||||
WindowManager.init();
|
||||
MainTerm.instance = new MainTerm();
|
||||
|
||||
if (Turtle.isTurtle()) {
|
||||
Turtle.instance = new Turtle();
|
||||
}
|
||||
|
||||
Routing.init();
|
||||
Net.init();
|
||||
|
||||
@@ -48,10 +36,6 @@ class Init {
|
||||
FS.makeDir("/var/ns");
|
||||
}
|
||||
|
||||
Init.mainEvent = MainLoop.add(() -> {
|
||||
KernelEvents.startEventLoop();
|
||||
});
|
||||
|
||||
ServiceManager.init();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package kernel;
|
||||
|
||||
import kernel.turtle.TurtleMutex;
|
||||
import kernel.turtle.Turtle;
|
||||
import kernel.peripherals.Peripherals.Peripheral;
|
||||
import kernel.log.Log;
|
||||
import lib.Pos;
|
||||
@@ -95,6 +97,7 @@ class KernelEvents {
|
||||
private static final onWebsocketSuccessTrigger:SignalTrigger<{url:String, handle:Any}> = Signal.trigger();
|
||||
|
||||
private static var stopLoop:Bool = false;
|
||||
private static var turtleCoroutine:Coroutine<Dynamic>;
|
||||
|
||||
@:allow(kernel.Init)
|
||||
private static function init() {
|
||||
@@ -133,8 +136,55 @@ class KernelEvents {
|
||||
/**
|
||||
Start pulling events. Blocking.
|
||||
**/
|
||||
@:allow(kernel.Init)
|
||||
@:allow(kernel.Entrypoint)
|
||||
private static function startEventLoop() {
|
||||
if (Turtle.isTurtle()) {
|
||||
turtleLoop();
|
||||
} else {
|
||||
runMainLoop();
|
||||
}
|
||||
}
|
||||
|
||||
@:allow(kernel.turtle.TurtleMutex)
|
||||
private static function startTurtleCoroutine() {
|
||||
turtleCoroutine = Coroutine.create(runTurtleLoop);
|
||||
Coroutine.resume(turtleCoroutine);
|
||||
}
|
||||
|
||||
private static function turtleLoop() {
|
||||
startTurtleCoroutine();
|
||||
|
||||
while (true) {
|
||||
var eventData = pullEvents();
|
||||
|
||||
if (eventData[1] == "turtle_response" || eventData[1] == "tthread") {
|
||||
var result = Coroutine.resume(turtleCoroutine, TableTools.unpack(eventData));
|
||||
|
||||
if (!result.success) {
|
||||
Log.error('Error while running turtle thread: ${result.result}');
|
||||
}
|
||||
|
||||
if (Coroutine.status(turtleCoroutine) == Dead) {
|
||||
Log.error('Turtle thread died');
|
||||
}
|
||||
} else {
|
||||
fireSignal(eventData[1], eventData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function runTurtleLoop() {
|
||||
while (!stopLoop) {
|
||||
if ((TableTools.pack(Coroutine.yield()))[1] != "tthread")
|
||||
continue;
|
||||
|
||||
if (stopLoop)
|
||||
continue;
|
||||
TurtleMutex.runThreadFunc();
|
||||
}
|
||||
}
|
||||
|
||||
private static function runMainLoop() {
|
||||
while (!stopLoop) {
|
||||
var event:Table<Int, Dynamic> = pullEvents();
|
||||
|
||||
@@ -156,7 +206,6 @@ class KernelEvents {
|
||||
Log.info('Shutting down event loop');
|
||||
stopLoop = true;
|
||||
MainTerm.instance.reset();
|
||||
Init.mainEvent.stop();
|
||||
}
|
||||
|
||||
private static function pullEvents():Table<Int, Dynamic> {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package kernel.binstore;
|
||||
|
||||
import bin.turtle.Excavate;
|
||||
import bin.turtle.Patrol;
|
||||
import bin.pathfinder.PFClient;
|
||||
import bin.ID;
|
||||
import bin.exporter.Res;
|
||||
@@ -30,7 +32,7 @@ class BinStore {
|
||||
{c: Net, name: "Net", aliases: ["net"]},
|
||||
{c: Redstone, name: "Redstone", aliases: ["redstone", "rs"]},
|
||||
{c: Terminal, name: "Terminal", aliases: ["terminal", "term"]},
|
||||
{c: Turtle, name: "Turtle", aliases: ["turtle"]},
|
||||
{c: Turtle, name: "Turtle", aliases: ["turtle", "t"]},
|
||||
{c: LSPS, name: "PM", aliases: ["lsps"]},
|
||||
{c: Service, name: "Service", aliases: ["service", "srv"]},
|
||||
{c: HelloWorldService, name: "HelloWorldService", aliases: ["hello-service"]},
|
||||
@@ -41,7 +43,9 @@ class BinStore {
|
||||
{c: ResManager, name: "ResManager", aliases: ["resmanager", "resmgr"]},
|
||||
{c: Res, name: "Res", aliases: ["res"]},
|
||||
{c: ID, name: "ID", aliases: ["id"]},
|
||||
{c: PFClient, name: "PFClient", aliases: ["pfclient"]}
|
||||
{c: PFClient, name: "PFClient", aliases: ["pfclient"]},
|
||||
{c: Patrol, name: "Patrol", aliases: ["patrol"]},
|
||||
{c: Excavate, name: "Excavate", aliases: ["excavate"]}
|
||||
];
|
||||
|
||||
public static function getBinByName(name:String):Null<Bin> {
|
||||
|
||||
@@ -69,8 +69,9 @@ class INS {
|
||||
}
|
||||
|
||||
private static function move(dir:Null<Pos3>) {
|
||||
Log.debug('INS move: $dir');
|
||||
var pos = GPS.getPosition();
|
||||
if (pos == null || dir == null)
|
||||
return;
|
||||
var newPos = pos + dir;
|
||||
GPS.setINSPosition(newPos);
|
||||
}
|
||||
@@ -82,7 +83,7 @@ class INS {
|
||||
public static function align():Promise<Noise> {
|
||||
Log.info("Aligning INS");
|
||||
return new Promise<Noise>((resolve, reject) -> {
|
||||
if (Turtle.instance.getFuelLevel() < 2) {
|
||||
if (Turtle.getFuelLevel() < 2) {
|
||||
Log.warn("Not enough fuel to align");
|
||||
reject(new Error("Not enough fuel to align"));
|
||||
return null;
|
||||
@@ -132,15 +133,15 @@ class INS {
|
||||
|
||||
// -1 = not moved, 0 = back, 1 = forward, 2 = left, 3 = right
|
||||
private static function tryMoving():Int {
|
||||
if (Turtle.instance.back().isSuccess()) {
|
||||
if (Turtle.back().isSuccess()) {
|
||||
return 0;
|
||||
} else if (Turtle.instance.forward().isSuccess()) {
|
||||
} else if (Turtle.forward().isSuccess()) {
|
||||
return 1;
|
||||
} else {
|
||||
Turtle.instance.turnLeft(); // TODO: Check if successfull
|
||||
if (Turtle.instance.forward().isSuccess()) {
|
||||
Turtle.turnLeft(); // TODO: Check if successfull
|
||||
if (Turtle.forward().isSuccess()) {
|
||||
return 2;
|
||||
} else if (Turtle.instance.back().isSuccess()) {
|
||||
} else if (Turtle.back().isSuccess()) {
|
||||
return 3;
|
||||
} else {
|
||||
// Can't move
|
||||
@@ -165,20 +166,20 @@ class INS {
|
||||
|
||||
private static function moveBack(moved:Int) {
|
||||
if (moved == 0) {
|
||||
Turtle.instance.forward();
|
||||
Turtle.forward();
|
||||
// cc.Turtle.forward();
|
||||
} else if (moved == 1) {
|
||||
Turtle.instance.back();
|
||||
Turtle.back();
|
||||
// cc.Turtle.back();
|
||||
} else if (moved == 2) {
|
||||
Turtle.instance.back();
|
||||
Turtle.back();
|
||||
// cc.Turtle.back();
|
||||
Turtle.instance.turnRight();
|
||||
Turtle.turnRight();
|
||||
// cc.Turtle.turnRight();
|
||||
} else if (moved == 3) {
|
||||
Turtle.instance.forward();
|
||||
Turtle.forward();
|
||||
// cc.Turtle.forward();
|
||||
Turtle.instance.turnRight();
|
||||
Turtle.turnRight();
|
||||
// cc.Turtle.turnRight();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package kernel.ps;
|
||||
|
||||
import kernel.turtle.TurtleMutex;
|
||||
import kernel.ps.ProcessManager.PID;
|
||||
import kernel.ui.WindowContext;
|
||||
import kernel.ui.WindowManager;
|
||||
@@ -104,7 +105,19 @@ class ProcessHandle {
|
||||
this.deferFuncs.push(func);
|
||||
}
|
||||
|
||||
function get_args():ReadOnlyArray<String> {
|
||||
public function get_args():ReadOnlyArray<String> {
|
||||
return this.config.args;
|
||||
}
|
||||
|
||||
public function claimTurtleMutex():Bool {
|
||||
if (TurtleMutex.claim(this.pid)) {
|
||||
this.addDeferFunc(() -> {
|
||||
TurtleMutex.release(this.pid);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +1,18 @@
|
||||
package kernel.turtle;
|
||||
|
||||
import kernel.log.Log;
|
||||
import kernel.turtle.Types;
|
||||
import kernel.gps.INS;
|
||||
|
||||
using tink.CoreApi;
|
||||
|
||||
class Turtle {
|
||||
public static var instance:Turtle;
|
||||
public static final MAX_SLOTS:Int = 16;
|
||||
|
||||
@:allow(kernel.Init)
|
||||
private function new() {
|
||||
if (!Turtle.isTurtle()) {
|
||||
Log.warn("Tried to initialize Turtle, but it is not available.");
|
||||
}
|
||||
}
|
||||
|
||||
public static function isTurtle():Bool {
|
||||
return true; // TODO: Implement
|
||||
return cc.Turtle != null;
|
||||
}
|
||||
|
||||
private function conterToOutcome(r:cc.Turtle.TurtleActionResult):Outcome<Noise, String> {
|
||||
private static function conterToOutcome(r:cc.Turtle.TurtleActionResult):Outcome<Noise, String> {
|
||||
if (r.successful) {
|
||||
return Outcome.Success(null);
|
||||
} else {
|
||||
@@ -33,7 +24,7 @@ class Turtle {
|
||||
}
|
||||
}
|
||||
|
||||
public function forward():Outcome<Noise, String> {
|
||||
public static function forward():Outcome<Noise, String> {
|
||||
var r = cc.Turtle.forward();
|
||||
var r2 = conterToOutcome(r);
|
||||
if (r2.isSuccess())
|
||||
@@ -41,7 +32,7 @@ class Turtle {
|
||||
return r2;
|
||||
}
|
||||
|
||||
public function back():Outcome<Noise, String> {
|
||||
public static function back():Outcome<Noise, String> {
|
||||
var r = cc.Turtle.back();
|
||||
var r2 = conterToOutcome(r);
|
||||
if (r2.isSuccess())
|
||||
@@ -49,7 +40,7 @@ class Turtle {
|
||||
return r2;
|
||||
}
|
||||
|
||||
public function up():Outcome<Noise, String> {
|
||||
public static function up():Outcome<Noise, String> {
|
||||
var r = cc.Turtle.up();
|
||||
var r2 = conterToOutcome(r);
|
||||
if (r2.isSuccess())
|
||||
@@ -57,7 +48,7 @@ class Turtle {
|
||||
return r2;
|
||||
}
|
||||
|
||||
public function down():Outcome<Noise, String> {
|
||||
public static function down():Outcome<Noise, String> {
|
||||
var r = cc.Turtle.down();
|
||||
var r2 = conterToOutcome(r);
|
||||
if (r2.isSuccess())
|
||||
@@ -65,7 +56,7 @@ class Turtle {
|
||||
return r2;
|
||||
}
|
||||
|
||||
public function turnLeft():Outcome<Noise, String> {
|
||||
public static function turnLeft():Outcome<Noise, String> {
|
||||
var r = cc.Turtle.turnLeft();
|
||||
var r2 = conterToOutcome(r);
|
||||
if (r2.isSuccess())
|
||||
@@ -73,7 +64,7 @@ class Turtle {
|
||||
return r2;
|
||||
}
|
||||
|
||||
public function turnRight():Outcome<Noise, String> {
|
||||
public static function turnRight():Outcome<Noise, String> {
|
||||
var r = cc.Turtle.turnRight();
|
||||
var r2 = conterToOutcome(r);
|
||||
if (r2.isSuccess())
|
||||
@@ -81,7 +72,7 @@ class Turtle {
|
||||
return r2;
|
||||
}
|
||||
|
||||
public function dig(dir:InteractDirections, ?toolSide:ToolSide):Outcome<Noise, String> {
|
||||
public static function dig(dir:InteractDirections, ?toolSide:ToolSide):Outcome<Noise, String> {
|
||||
var r:cc.Turtle.TurtleActionResult;
|
||||
|
||||
// FIXME: upstream needs to be fixed to accept ToolSide
|
||||
@@ -96,7 +87,7 @@ class Turtle {
|
||||
return conterToOutcome(r);
|
||||
}
|
||||
|
||||
public function place(dir:InteractDirections):Outcome<Noise, String> {
|
||||
public static function place(dir:InteractDirections):Outcome<Noise, String> {
|
||||
var r:cc.Turtle.TurtleActionResult;
|
||||
switch dir {
|
||||
case Front:
|
||||
@@ -109,7 +100,7 @@ class Turtle {
|
||||
return conterToOutcome(r);
|
||||
}
|
||||
|
||||
public function placeSign(dir:InteractDirections, text:String):Outcome<Noise, String> {
|
||||
public static function placeSign(dir:InteractDirections, text:String):Outcome<Noise, String> {
|
||||
var r:cc.Turtle.TurtleActionResult;
|
||||
switch dir {
|
||||
case Front:
|
||||
@@ -122,12 +113,12 @@ class Turtle {
|
||||
return conterToOutcome(r);
|
||||
}
|
||||
|
||||
public function drop(dir:InteractDirections, ?count:Int):Outcome<Noise, String> {
|
||||
public static function drop(dir:InteractDirections, ?count:Int):Outcome<Noise, String> {
|
||||
var r = cc.Turtle.drop(count);
|
||||
return conterToOutcome(r);
|
||||
}
|
||||
|
||||
public function selectSlot(slot:TurtleSlot):Outcome<Noise, Noise> {
|
||||
public static function selectSlot(slot:TurtleSlot):Outcome<Noise, Noise> {
|
||||
// TODO: slot in bounds?
|
||||
|
||||
var r = cc.Turtle.select(slot + 1);
|
||||
@@ -135,19 +126,19 @@ class Turtle {
|
||||
return (r) ? Outcome.Success(null) : Outcome.Failure("Slot out of bounds");
|
||||
}
|
||||
|
||||
public function getItemCount(?slot:TurtleSlot):Int {
|
||||
public static function getItemCount(?slot:TurtleSlot):Int {
|
||||
// TODO: slot in bounds?
|
||||
|
||||
return cc.Turtle.getItemCount(slot + 1);
|
||||
}
|
||||
|
||||
public function getItemSpace(?slot:TurtleSlot):Int {
|
||||
public static function getItemSpace(?slot:TurtleSlot):Int {
|
||||
// TODO: slot in bounds?
|
||||
|
||||
return cc.Turtle.getItemSpace(slot + 1);
|
||||
}
|
||||
|
||||
public function detect(dir:InteractDirections):Bool {
|
||||
public static function detect(dir:InteractDirections):Bool {
|
||||
switch dir {
|
||||
case Front:
|
||||
return cc.Turtle.detect();
|
||||
@@ -158,7 +149,7 @@ class Turtle {
|
||||
}
|
||||
}
|
||||
|
||||
public function compareToSlot(dir:InteractDirections):Bool {
|
||||
public static function compareToSlot(dir:InteractDirections):Bool {
|
||||
switch dir {
|
||||
case Front:
|
||||
return cc.Turtle.compare();
|
||||
@@ -169,7 +160,7 @@ class Turtle {
|
||||
}
|
||||
}
|
||||
|
||||
public function attack(dir:InteractDirections, ?toolSide:ToolSide):Outcome<Noise, String> {
|
||||
public static function attack(dir:InteractDirections, ?toolSide:ToolSide):Outcome<Noise, String> {
|
||||
var r:cc.Turtle.TurtleActionResult;
|
||||
|
||||
// FIXEM: upstream needs to be fixed to accept ToolSide
|
||||
@@ -185,7 +176,7 @@ class Turtle {
|
||||
return conterToOutcome(r);
|
||||
}
|
||||
|
||||
public function suckItem(dir:InteractDirections, ?ammount:Int):Outcome<Noise, String> {
|
||||
public static function suckItem(dir:InteractDirections, ?ammount:Int):Outcome<Noise, String> {
|
||||
// TODO: ammount in bounds?
|
||||
|
||||
var r:cc.Turtle.TurtleActionResult;
|
||||
@@ -201,40 +192,40 @@ class Turtle {
|
||||
return conterToOutcome(r);
|
||||
}
|
||||
|
||||
public function getFuelLevel():Int {
|
||||
public static function getFuelLevel():Int {
|
||||
var r = cc.Turtle.getFuelLevel(); // FIXME: can be a string. Has to be fixed upstream
|
||||
return r;
|
||||
}
|
||||
|
||||
public function refuel(?ammount:Int):Outcome<Noise, String> {
|
||||
public static function refuel(?ammount:Int):Outcome<Noise, String> {
|
||||
var r = cc.Turtle.refuel(ammount);
|
||||
return conterToOutcome(r);
|
||||
}
|
||||
|
||||
public function canRefultWithSlot():Bool {
|
||||
public static function canRefultWithSlot():Bool {
|
||||
var r = cc.Turtle.refuel(0);
|
||||
return r.successful;
|
||||
}
|
||||
|
||||
public function compareSlot(otherSlot:TurtleSlot):Bool {
|
||||
public static function compareSlot(otherSlot:TurtleSlot):Bool {
|
||||
return cc.Turtle.compareTo(otherSlot + 1);
|
||||
}
|
||||
|
||||
public function transfer(from:TurtleSlot, to:TurtleSlot, ?count:Int):Outcome<Noise, Noise> {
|
||||
this.selectSlot(from);
|
||||
public static function transfer(from:TurtleSlot, to:TurtleSlot, ?count:Int):Outcome<Noise, Noise> {
|
||||
selectSlot(from);
|
||||
var r = cc.Turtle.transferTo(to + 1, count);
|
||||
return r ? Outcome.Success(null) : Outcome.Failure(null);
|
||||
}
|
||||
|
||||
public function getSelectedSlot():TurtleSlot {
|
||||
public static function getSelectedSlot():TurtleSlot {
|
||||
return cc.Turtle.getSelectedSlot() - 1;
|
||||
}
|
||||
|
||||
public function getFuelLimit():Int {
|
||||
public static function getFuelLimit():Int {
|
||||
return cc.Turtle.getFuelLimit(); // FIXME: can be a string. Has to be fixed upstream
|
||||
}
|
||||
|
||||
public function equip(side:ToolSide):Outcome<Noise, String> {
|
||||
public static function equip(side:ToolSide):Outcome<Noise, String> {
|
||||
switch side {
|
||||
case Left:
|
||||
return conterToOutcome(cc.Turtle.equipLeft());
|
||||
@@ -243,7 +234,7 @@ class Turtle {
|
||||
}
|
||||
}
|
||||
|
||||
public function inspect(dir:InteractDirections):Outcome<BlockInspect, String> {
|
||||
public static function inspect(dir:InteractDirections):Outcome<BlockInspect, String> {
|
||||
var r:cc.Turtle.TurtleInspectResult;
|
||||
switch dir {
|
||||
case Front:
|
||||
@@ -266,7 +257,7 @@ class Turtle {
|
||||
});
|
||||
}
|
||||
|
||||
public function getItemDetail(?detailed:Bool = false, ?slot:TurtleSlot):Option<ItemInspect> {
|
||||
public static function getItemDetail(?detailed:Bool = false, ?slot:TurtleSlot):Option<ItemInspect> {
|
||||
var r = cc.Turtle.getItemDetail(slot + 1); // FIXME: can take detailed as flag. Has to be fixed upstream
|
||||
|
||||
if (r == null) {
|
||||
@@ -281,7 +272,7 @@ class Turtle {
|
||||
});
|
||||
}
|
||||
|
||||
public function craft(?limit:Int = 64):Outcome<Noise, String> {
|
||||
public static function craft(?limit:Int = 64):Outcome<Noise, String> {
|
||||
if (limit < 1 || limit > 64) {
|
||||
return Outcome.Failure("Crafting limit out of bounds");
|
||||
}
|
||||
|
||||
52
src/kernel/turtle/TurtleMutex.hx
Normal file
52
src/kernel/turtle/TurtleMutex.hx
Normal file
@@ -0,0 +1,52 @@
|
||||
package kernel.turtle;
|
||||
|
||||
import kernel.log.Log;
|
||||
import cc.OS;
|
||||
import kernel.ps.ProcessManager.PID;
|
||||
|
||||
/**
|
||||
Make sure only one process can access the turtle at a time.
|
||||
**/
|
||||
class TurtleMutex {
|
||||
private static var claimedPid:PID = -1;
|
||||
public static var threadFunc:() -> Void;
|
||||
|
||||
@:allow(kernel.ps.ProcessHandle)
|
||||
private static function claim(pid:PID):Bool {
|
||||
if (claimedPid == -1) {
|
||||
claimedPid = pid;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@:allow(kernel.ps.ProcessHandle)
|
||||
private static function release(pid:PID) {
|
||||
if (claimedPid == pid) {
|
||||
claimedPid = -1;
|
||||
stopTurtleThread();
|
||||
}
|
||||
}
|
||||
|
||||
@:allow(kernel.KernelEvents)
|
||||
private static function runThreadFunc() {
|
||||
if (threadFunc != null) {
|
||||
try {
|
||||
threadFunc();
|
||||
} catch (e) {
|
||||
Log.error("Error in tthread: " + e);
|
||||
}
|
||||
threadFunc = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static function runInTThread(func:() -> Void) {
|
||||
threadFunc = func;
|
||||
OS.queueEvent("tthread");
|
||||
}
|
||||
|
||||
public static function stopTurtleThread() {
|
||||
threadFunc = null;
|
||||
KernelEvents.startTurtleCoroutine();
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ abstract class CLIAppBase implements Process {
|
||||
private final _subcommandsAsync:Map<String, (Array<String>) -> Future<Bool>> = [];
|
||||
private final _subcommandsSynopsis:Array<String> = [];
|
||||
|
||||
public function run(handle:ProcessHandle) {
|
||||
public final function run(handle:ProcessHandle) {
|
||||
this.handle = handle;
|
||||
|
||||
var subcommand = handle.args[0];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package lib;
|
||||
|
||||
import lua.TableTools;
|
||||
import kernel.KernelEvents;
|
||||
import kernel.log.Log;
|
||||
import lua.NativeStringTools;
|
||||
@@ -37,6 +38,27 @@ class Debug {
|
||||
Log.debug("\n" + lines.join("\n"));
|
||||
}
|
||||
|
||||
public static function printArgs(?pos:haxe.PosInfos) {
|
||||
var info = lua.Debug.getinfo(2);
|
||||
|
||||
var args = "";
|
||||
|
||||
for (i in 1...info.nparams + 1) {
|
||||
var t = TableTools.pack(lua.Debug.getlocal(2, i));
|
||||
if (t[1] == "self") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (args != "") {
|
||||
args += ", ";
|
||||
}
|
||||
|
||||
args += t[1] + ":" + t[2];
|
||||
}
|
||||
|
||||
Log.debug('${pos.className}.${pos.methodName}($args)');
|
||||
}
|
||||
|
||||
#if Debug
|
||||
public static function printKernelEventsCount() {
|
||||
KernelEvents.printListenerCount();
|
||||
|
||||
17
src/lib/turtle/Helper.hx
Normal file
17
src/lib/turtle/Helper.hx
Normal file
@@ -0,0 +1,17 @@
|
||||
package lib.turtle;
|
||||
|
||||
using tink.CoreApi;
|
||||
|
||||
class Helper {
|
||||
public static function times(func:Void->Outcome<Noise, String>, times:Int):Outcome<Noise, {step:Int, error:String}> {
|
||||
for (i in 0...times) {
|
||||
switch (func()) {
|
||||
case Success(_):
|
||||
case Failure(err):
|
||||
return Failure({step: i, error: err});
|
||||
}
|
||||
}
|
||||
|
||||
return Success(null);
|
||||
}
|
||||
}
|
||||
34
src/lib/turtle/TurtleAppBase.hx
Normal file
34
src/lib/turtle/TurtleAppBase.hx
Normal file
@@ -0,0 +1,34 @@
|
||||
package lib.turtle;
|
||||
|
||||
import kernel.turtle.TurtleMutex;
|
||||
import kernel.ps.ProcessHandle;
|
||||
import kernel.ps.Process;
|
||||
|
||||
abstract class TurtleAppBase implements Process {
|
||||
private var handle:ProcessHandle;
|
||||
|
||||
private var _initFunc:Void->Void;
|
||||
private var _turtleFunc:Void->Void;
|
||||
|
||||
public function new(initFunc:Null<Void->Void>, turtleFunc:Void->Void) {
|
||||
this._initFunc = initFunc;
|
||||
this._turtleFunc = turtleFunc;
|
||||
}
|
||||
|
||||
public final function run(handle:ProcessHandle) {
|
||||
this.handle = handle;
|
||||
|
||||
if (!handle.claimTurtleMutex()) {
|
||||
handle.writeLine("Failed to claim turtle mutex");
|
||||
handle.close();
|
||||
}
|
||||
|
||||
if (this._initFunc != null) {
|
||||
this._initFunc();
|
||||
}
|
||||
|
||||
if (this._turtleFunc != null) {
|
||||
TurtleMutex.runInTThread(this._turtleFunc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,25 +71,25 @@ class TurtleExecuter {
|
||||
private function executeInst(instruction:TurtleInstruction):Outcome<Noise, String> {
|
||||
switch instruction {
|
||||
case Forward:
|
||||
return Turtle.instance.forward();
|
||||
return Turtle.forward();
|
||||
case Back:
|
||||
return Turtle.instance.back();
|
||||
return Turtle.back();
|
||||
case Up:
|
||||
return Turtle.instance.up();
|
||||
return Turtle.up();
|
||||
case Down:
|
||||
return Turtle.instance.down();
|
||||
return Turtle.down();
|
||||
case TurnLeft:
|
||||
return Turtle.instance.turnLeft();
|
||||
return Turtle.turnLeft();
|
||||
case TurnRight:
|
||||
return Turtle.instance.turnRight();
|
||||
return Turtle.turnRight();
|
||||
case Dig(dir):
|
||||
return Turtle.instance.dig(dir);
|
||||
return Turtle.dig(dir);
|
||||
case Place(dir):
|
||||
return Turtle.instance.place(dir);
|
||||
return Turtle.place(dir);
|
||||
case PlacseSign(dir, text):
|
||||
return Turtle.instance.placeSign(dir, text);
|
||||
return Turtle.placeSign(dir, text);
|
||||
case Select(slot):
|
||||
var r = Turtle.instance.selectSlot(slot);
|
||||
var r = Turtle.selectSlot(slot);
|
||||
if (r.isSuccess()) {
|
||||
return Outcome.Success(null);
|
||||
} else {
|
||||
|
||||
@@ -37,9 +37,9 @@ class TurtleExt {
|
||||
var ret:Int = 0;
|
||||
|
||||
for (i in 0...Turtle.MAX_SLOTS) {
|
||||
var slotItem = Turtle.instance.getItemDetail(i).orNull();
|
||||
var slotItem = Turtle.getItemDetail(i).orNull();
|
||||
if (slotItem != null && slotItem.name == item) {
|
||||
ret += Turtle.instance.getItemSpace(i);
|
||||
ret += Turtle.getItemSpace(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user