diff --git a/src/bin/Turtle.hx b/src/bin/Turtle.hx deleted file mode 100644 index 3370481..0000000 --- a/src/bin/Turtle.hx +++ /dev/null @@ -1,62 +0,0 @@ -package bin; - -import lib.turtle.InvManager; -import lib.CLIAppBase; - -using tink.CoreApi; - -@:build(macros.Binstore.includeBin("Turtle", ["turtle", "t"])) -class Turtle extends CLIAppBase { - public function new() { - registerSyncSubcommand("forward", (args) -> { - return checkAvailable() && perform(kernel.turtle.Turtle.forward()); - }); - - registerSyncSubcommand("back", (args) -> { - return checkAvailable() && perform(kernel.turtle.Turtle.back()); - }); - - registerSyncSubcommand("left", (args) -> { - return checkAvailable() && perform(kernel.turtle.Turtle.turnLeft()); - }); - - registerSyncSubcommand("right", (args) -> { - return checkAvailable() && perform(kernel.turtle.Turtle.turnRight()); - }); - - registerSyncSubcommand("up", (args) -> { - return checkAvailable() && perform(kernel.turtle.Turtle.up()); - }); - - registerSyncSubcommand("down", (args) -> { - return checkAvailable() && perform(kernel.turtle.Turtle.down()); - }); - - registerSyncSubcommand("defrag", (args) -> { - if (!checkAvailable()) { - return false; - } - - InvManager.defrag(); - return true; - }); - } - - 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):Bool { - switch outcome { - case Success(_): - return true; - case Failure(error): - handle.write(error); - return false; - } - } -} diff --git a/src/bin/TurtleCtl.hx b/src/bin/TurtleCtl.hx new file mode 100644 index 0000000..706be0d --- /dev/null +++ b/src/bin/TurtleCtl.hx @@ -0,0 +1,103 @@ +package bin; + +import kernel.turtle.TurtleMutex; +import kernel.turtle.Turtle; +import lib.turtle.InvManager; +import lib.CLIAppBase; + +using tink.CoreApi; + +@:build(macros.Binstore.includeBin("Turtle", ["turtle", "t"])) +class TurtleCtl extends CLIAppBase { + public function new() { + registerAsyncSubcommand("f", (args) -> { + return asynPerform(Turtle.forward, parseTimes(args)); + }, ""); + + registerAsyncSubcommand("b", (args) -> { + return asynPerform(Turtle.back, parseTimes(args)); + }, ""); + + registerAsyncSubcommand("l", (args) -> { + return asynPerform(Turtle.turnLeft, parseTimes(args)); + }, ""); + + registerAsyncSubcommand("r", (args) -> { + return asynPerform(Turtle.turnRight, parseTimes(args)); + }, ""); + + registerAsyncSubcommand("u", (args) -> { + return asynPerform(Turtle.up, parseTimes(args)); + }, ""); + + registerAsyncSubcommand("d", (args) -> { + return asynPerform(Turtle.down, parseTimes(args)); + }, ""); + + registerAsyncSubcommand("defrag", (args) -> { + return asynPerform(() -> { + // TODO: when defrag can fail return that error + InvManager.defrag(); + return Success(null); + }, 1); + }); + + registerSyncSubcommand("fuel", (args) -> { + var lvl = Turtle.getFuelLevel(); + var limit = Turtle.getFuelLimit(); + handle.writeLine('${lvl}/${limit} (${(lvl / limit) * 100}%)'); + return true; + }); + } + + private function asynPerform(op:Void->Outcome, times:Int):Future { + return new Future((wakeup) -> { + if (times == 0) { + wakeup(false); + return null; + } + + if (!Turtle.isTurtle()) { + handle.write("This is not a turtle!"); + wakeup(false); + return null; + } + + if (!handle.claimTurtleMutex()) { + handle.writeLine("Failed to claim mutex"); + wakeup(false); + return null; + } + + TurtleMutex.runInTThread(() -> { + for (i in 0...times) { + switch op() { + case Success(_): + case Failure(failure): + handle.writeLine('Failed: $failure'); + wakeup(false); + return; + } + } + + wakeup(true); + }); + + return null; + }); + } + + private function parseTimes(args:Array):Int { + if (args.length > 0) { + var num = Std.parseInt(args[0]); + if (num == null) { + handle.writeLine("Failed to parse args"); + return 0; + } else { + return num; + } + } else { + return 1; + } + } +}