Compare commits

...

11 Commits

Author SHA1 Message Date
a568c9cdd8 added example excavate app 2023-08-05 11:42:38 +02:00
44772557ba fixed INS when no GPS fix 2023-08-05 11:42:15 +02:00
0540cc465a added example turtle program 2023-08-03 18:01:12 +02:00
21387cd8e7 you can stop the turtle thread now 2023-08-02 17:14:54 +02:00
a46760e587 added seperate turtle thread 2023-08-02 16:32:52 +02:00
c83f457968 clipAppBase run final 2023-08-02 16:31:40 +02:00
b8f5ffb93a made Turtle a static class 2023-08-01 13:19:01 +02:00
3c59e045de precommit add formatted files 2023-08-01 13:16:18 +02:00
4b8bc87db9 added printArgs debug function 2023-08-01 13:15:56 +02:00
0c7280a2f5 fixed turtle output text 2023-07-31 16:42:17 +02:00
98b8465436 isTurtle check 2023-07-31 16:40:11 +02:00
18 changed files with 369 additions and 94 deletions

View File

@@ -8,7 +8,7 @@ set -e
# format
make format
git diff --name-only --cached | xargs -l git add
# build
make build

View File

@@ -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(_):

View 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
View 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();
}
});
}
}

View File

@@ -16,5 +16,7 @@ class Entrypoint {
} catch (e) {
Log.error('Error in startup: ${e.toString()}');
}
KernelEvents.startEventLoop();
}
}

View File

@@ -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();
}
}

View File

@@ -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> {

View File

@@ -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> {

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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");
}

View 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();
}
}

View File

@@ -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];

View File

@@ -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
View 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);
}
}

View 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);
}
}
}

View File

@@ -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 {

View File

@@ -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);
}
}