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 } private function conterToOutcome(r:cc.Turtle.TurtleActionResult):Outcome { if (r.successful) { return Outcome.Success(null); } else { if (r.error != null) { return Outcome.Failure(r.error); } else { return Outcome.Failure("Unknown error"); } } } public function forward():Outcome { var r = cc.Turtle.forward(); var r2 = conterToOutcome(r); if (r2.isSuccess()) INS.moveForward(); return r2; } public function back():Outcome { var r = cc.Turtle.back(); var r2 = conterToOutcome(r); if (r2.isSuccess()) INS.moveBackward(); return r2; } public function up():Outcome { var r = cc.Turtle.up(); var r2 = conterToOutcome(r); if (r2.isSuccess()) INS.moveUp(); return r2; } public function down():Outcome { var r = cc.Turtle.down(); var r2 = conterToOutcome(r); if (r2.isSuccess()) INS.moveDown(); return r2; } public function turnLeft():Outcome { var r = cc.Turtle.turnLeft(); var r2 = conterToOutcome(r); if (r2.isSuccess()) INS.turnRight(); return r2; } public function turnRight():Outcome { var r = cc.Turtle.turnRight(); var r2 = conterToOutcome(r); if (r2.isSuccess()) INS.turnRight(); return r2; } public function dig(dir:InteractDirections, ?toolSide:ToolSide):Outcome { var r:cc.Turtle.TurtleActionResult; // FIXME: upstream needs to be fixed to accept ToolSide switch dir { case Front: r = cc.Turtle.dig(); case Up: r = cc.Turtle.digUp(); case Down: r = cc.Turtle.digDown(); } return conterToOutcome(r); } public function place(dir:InteractDirections):Outcome { var r:cc.Turtle.TurtleActionResult; switch dir { case Front: r = cc.Turtle.place(); case Up: r = cc.Turtle.placeUp(); case Down: r = cc.Turtle.placeDown(); } return conterToOutcome(r); } public function placeSign(dir:InteractDirections, text:String):Outcome { var r:cc.Turtle.TurtleActionResult; switch dir { case Front: r = cc.Turtle.place(text); case Up: r = cc.Turtle.placeUp(); // FIXME: fix upstream to accept text case Down: r = cc.Turtle.placeDown(); } return conterToOutcome(r); } public function drop(dir:InteractDirections, ?count:Int):Outcome { var r = cc.Turtle.drop(count); return conterToOutcome(r); } public function selectSlot(slot:TurtleSlot):Outcome { // TODO: slot in bounds? var r = cc.Turtle.select(slot + 1); return (r) ? Outcome.Success(null) : Outcome.Failure("Slot out of bounds"); } public function getItemCount(?slot:TurtleSlot):Int { // TODO: slot in bounds? return cc.Turtle.getItemCount(slot + 1); } public function getItemSpace(?slot:TurtleSlot):Int { // TODO: slot in bounds? return cc.Turtle.getItemSpace(slot + 1); } public function detect(dir:InteractDirections):Bool { switch dir { case Front: return cc.Turtle.detect(); case Up: return cc.Turtle.detectUp(); case Down: return cc.Turtle.detectDown(); } } public function compareToSlot(dir:InteractDirections):Bool { switch dir { case Front: return cc.Turtle.compare(); case Up: return cc.Turtle.compareUp(); case Down: return cc.Turtle.compareDown(); } } public function attack(dir:InteractDirections, ?toolSide:ToolSide):Outcome { var r:cc.Turtle.TurtleActionResult; // FIXEM: upstream needs to be fixed to accept ToolSide switch dir { case Front: r = cc.Turtle.attack(); case Up: r = cc.Turtle.attackUp(); case Down: r = cc.Turtle.attackDown(); } return conterToOutcome(r); } public function suckItem(dir:InteractDirections, ?ammount:Int):Outcome { // TODO: ammount in bounds? var r:cc.Turtle.TurtleActionResult; switch dir { case Front: r = cc.Turtle.suck(ammount); case Up: r = cc.Turtle.suckUp(ammount); case Down: r = cc.Turtle.suckDown(ammount); } return conterToOutcome(r); } public 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 { var r = cc.Turtle.refuel(ammount); return conterToOutcome(r); } public function canRefultWithSlot():Bool { var r = cc.Turtle.refuel(0); return r.successful; } public function compareSlot(otherSlot:TurtleSlot):Bool { return cc.Turtle.compareTo(otherSlot + 1); } public function transfer(from:TurtleSlot, to:TurtleSlot, ?count:Int):Outcome { this.selectSlot(from); var r = cc.Turtle.transferTo(to + 1, count); return r ? Outcome.Success(null) : Outcome.Failure(null); } public function getSelectedSlot():TurtleSlot { return cc.Turtle.getSelectedSlot() - 1; } public function getFuelLimit():Int { return cc.Turtle.getFuelLimit(); // FIXME: can be a string. Has to be fixed upstream } public function equip(side:ToolSide):Outcome { switch side { case Left: return conterToOutcome(cc.Turtle.equipLeft()); case Right: return conterToOutcome(cc.Turtle.equipRight()); } } public function inspect(dir:InteractDirections):Outcome { var r:cc.Turtle.TurtleInspectResult; switch dir { case Front: r = cc.Turtle.inspect(); case Up: r = cc.Turtle.inspectUp(); case Down: r = cc.Turtle.inspectDown(); } if (!r.successful) { return Outcome.Failure(r.result); } // TODO: check if this is correct return Outcome.Success({ name: (r.result : cc.Turtle.TurtleBlockDetail).name, state: (r.result : cc.Turtle.TurtleBlockDetail).state, metadata: (r.result : cc.Turtle.TurtleBlockDetail).metadata, }); } public function getItemDetail(?detailed:Bool = false, ?slot:TurtleSlot):Option { var r = cc.Turtle.getItemDetail(slot + 1); // FIXME: can take detailed as flag. Has to be fixed upstream if (r == null) { return None; } // TODO: check if this is correct return Some({ name: r.name, count: r.count, damage: r.damage, }); } public function craft(?limit:Int = 64):Outcome { if (limit < 1 || limit > 64) { return Outcome.Failure("Crafting limit out of bounds"); } var r = cc.Turtle.craft(limit); return conterToOutcome(r); } }